import java.lang.Math;
public class Driver {
public static void main(String[] args) {
System.out.println(Math.abs(-10));
System.out.println(Math.abs(8));
}
}
10
8
-최소값, 최대값
import java.lang.Math;
public class Driver {
public static void main(String[] args) {
System.out.println(Math.min(4, 10)); // 최솟값
System.out.println(Math.max(4, 10)); // 최댓값
}
}
4
10
-Random 클래스
-> 인스턴스를 생성해서 사용해야함
import java.util.Random;
public class Driver {
public static void main(String[] args) {
Random rand = new Random();
System.out.println(rand.nextInt(10)); // 0 이상 9 이하의 랜덤한 값
}
}
-a ~ b 사이의 랜덤 값
import java.util.Random;
public class Driver {
public static void main(String[] args) {
Random rand = new Random();
int min = 10;
int max = 30;
System.out.println(rand.nextInt((max - min) + 1) + min); // 10 이상 30 이하의 랜덤한 값
}
}
System.out.println(123 == 123);
System.out.println(new Integer(123) == new Integer(123));
true
false //참조형의 비교 연산자는 가리키는 객체가 같읕지 비교하기 때문입니다. 두 생성자를 통해 만든 다른 객체이기 때문에
두 String 인스턴스를 비교할 때 처럼 equals 메소드를 쓰면 '값'이 같은지 확인
ArrayList<test> myList = new ArrayList<test>(); //선언방식
<> 안에 들어가는 것 : List 타입
<주요 메소드>
myList.add(Object elem)
객체 매개변수(elem)를 목록에 추가
myList.remove(int index)
index 매개변수로 지정한 위치에 있는 객체를 제거
myList.remove(Object elem)
주어진 객체가 List에 있으면 그 객체를 제거
myList.contains(Object elem)
객체 매개변수 elem에 매치되는 것이 있으면 '참'을 리턴
myList.isEmpty()
목록에 아무 원소도 없으면 '참'을 리턴
myList.indexOf(Object elem)
객체 매개변수(elem)의 인덱스 또는 -1을 리턴
myList.size()
현재 목록에 들어있는 원소의 개수를 리턴
get(int index)
주어진 index 매개변수 위치에 있는 객체를 리턴
5.HashMap
-> 'value(원소)'와, 그 원소를 가리키는 'key' 값을 같이 저장
-사용
->HashMap의 키로는 String을 쓰는 것이 가장 일반적
-선언하기
HashMap<String, Pokemon> pokedex = new HashMap<>();
-key-Value 쌍 추가하기(put 메소드)
pokedex.put("피카츄", new Pokemon("피카츄"));
pokedex.put("파이리", new Pokemon("파이리"));
pokedex.put("이상해씨", new Pokemon("이상해씨"));
pokedex.put("이상해풀", new Pokemon("이상해풀"));
pokedex.put("이상해꽃", new Pokemon("이상해꽃"));
-값 꺼내기(get 메소드)
Pokemon pikachu = pokedex.get("피카츄");
-원소 덮어쓰기
pokedex.put("피카츄", new Pokemon("라이츄");
-반복문을 통해 HashMap 탐색하기
HashMap의 keyset메소드는 모든 key를 담고 있는 Set을 리턴
Set은 List나 Map과 같이 원소를 담고 있는 자료형 중 하나이며 'for each'문으로 탐색이 가능
for (String key : pokedex.keySet()) {
System.out.println(pokedex.get(key));
}
(심화) 동작원리
HashMap의 key는 'hashcode'라는 것으로 관리
hashcode는 모든 클래스의 인스턴스가 가진 고유한 값인데, 인스턴스마다 다르기 때문에 HashMap이 key를 구분하는 값으로 사용
(여러 인스턴스가 같은 hashcode를 가질 수 있으며, 이 경우 HashMap에선 key.equals(anotherKey) 메소드로 구분).
일반적인 클래스는 인스턴스 생성시 hashcode 값이 결정
즉, 같은 정보를 담고 있는 두 인스턴스가 서로 다른 hashcode를 가질 수 있다
그런데 String은 서로 다른 인스턴스라도 안의 내용이 같으면 같은 hashcode를 가짐.
int a = 3;
int b = a;
System.out.println(a); // 3 출력
System.out.println(b); // 3 출력
a = 4;
System.out.println(a); // 4 출력
System.out.println(b); // 3 출력
b = 7;
System.out.println(a); // 4 출력
System.out.println(b); // 7 출력
-참조형 : Person, String , int[] 등 클래스 기반 자료형
Person p1, p2;
p1 = new Person("김신의", 28);
p2 = p1;
p2.setName("문종모");
System.out.println(p1.getName()); //문종모
System.out.println(p2.getName()); //문종모
p1은 '김신의'라는 이름을 가진 Person 인스턴스가 저장되어있음
p2 = p1 => p2에게 같은 영역을 가리키라
p2.setName("문종모") 를 하면 그 영역에 있는 인스턴스의 name -> 문종모 로 바뀜
p2, p1은 모두 같은 영역을 가리키고 있으니 두 출력 값은 모두 '문종모'
배열 또한 객체이기에 참조형
int[] a = new int[3];
int[] b = a;
a[0] = 1;
b[0] = 2;
System.out.println(a[0]); //2
System.out.println(b[0]); //2
2. null
비어있음 -> null 로 표현
단, null은 참조형 변수(Reference Type)만 가질 수 있는 값
Person p1 = null;
System.out.println(p1); //null
//만약, null을 보관하고 있는 변수의 메소드를 호출하려고 하면 오류 발생
Person p1 = null;
p1.getName(); //Exception in thread "main" java.lang.NullPointerException
//대처법
Person[] people = new Person[5];
people[0] = new Person("김신의", 28);
people[2] = new Person("문종모", 26);
people[3] = new Person("서혜린", 21);
for (int i = 0; i < people.length; i++) {
Person p = people[i];
if (p != null) {
System.out.println(p.getName());
} else {
System.out.println(i + "번 자리는 비었습니다.");
}
}
/*김신의
1번 자리는 비었습니다.
문종모
서혜린
4번 자리는 비었습니다.*/
3. 숏서킷 연산(Short-Circuit Evaluation)
-> 실의 결과값이 이미 결정된 경우 미리 멈추는 것
-And (&&)
boolean newBoolean = m1() && m2() && m3();
-> newBoolean이 true가 되기 위해서는 m1(), m2(), m3()가 모두 true를 리턴해야함
-Or (||)
boolean newBoolean = m1() || m2() || m3();
-> newBoolean이 false이기 위해서는 m1(), m2(), m3()의 리턴값이 모두 false이어야 함
4. 변수 안전하게 만들기(final)
-변수 정의 시 final을 써주면, 그 변수는 상수가 됨 -> 한번 정의하면 다시 바꿀 수 없음
-참조형
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public static void main(String[] args) {
final Person p1 = new Person("김신의");
p1.setName("문종모");
System.out.println(p1.getName());
}
}
//문종모
->p1의 이름을 못 바꾸도록 만들고 싶으면 Person 클래스 내에서 name을 final로 정의해주면 됨.
5. 인스턴스 변수 vs 클래스 변수
-인스턴스 변수
public class Person {
int count;
}
//새로운 Person 인스턴스를 생성할 때마다 각 인스턴스의 count변수를 계속 바꿔야함
public static void main(String[] args) {
Person p1 = new Person();
p1.count++;
Person p2 = new Person();
p1.count++;
p2.count = p1.count;
Person p3 = new Person();
p1.count++;
p2.count++;
p3.count = p2.count;
Person p4 = new Person();
p1.count++;
p2.count++;
p3.count++;
p4.count = p3.count;
System.out.println(p1.count); //4
System.out.println(p2.count); //4
System.out.println(p3.count); //4
System.out.println(p4.count); //4
}
-클래스 변수 버전
public class Person {
static int count;
}
//count는 특정 인스턴스에 해당되는게 아니라, Person 클래스 전체에 해당되는 것
//count 부를 때 대문자로 쓴 클래스 이름을 사용해서 Person.count 써준다
public static void main(String[] args) {
Person p1 = new Person();
Person.count++;
Person p2 = new Person();
Person.count++;
Person p3 = new Person();
Person.count++;
Person p4 = new Person();
Person.count++;
System.out.println(Person.count);
} //4
-> Person.count++ 매번해주는 것을 개선시켜주자
public class Person {
static int count;
public Person() {
count++;
}
}
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();
Person p3 = new Person();
Person p4 = new Person();
System.out.println(Person.count);
}//4
-> 변수가 클래스 자체에 해당될 때는 static 써서 클래스 변수로 만들어주자!
-상수
상수는 인스턴스에 해당되는 것이 아니며, 여러 복사본 대신 한 값만 저장해둔다
public class CodeitConstants {
public static final double PI = 3.141592653589793;
public static final double EULERS_NUMBER = 2.718281828459045;
public static final String THIS_IS_HOW_TO_NAME_CONSTANT_VARIABLE = "Hello";
public static void main(String[] args) {
System.out.println(CodeitConstants.PI + CodeitConstants.EULERS_NUMBER);
}
}//5.859874482048838
6.인스턴스 메소드 vs 클래스 메소드
-클래스 메소드 : 인스턴스가 아닌 클래스에 속한 메소드
-> 인스턴스를 생성하지 않고도 바로 실행할 수 있다
<클래스 메소드 예시>
-Math 클래스
import java.lang.Math;
public class Driver {
public static void main(String[] args) {
System.out.println(Math.abs(-10)); // 절댓값
System.out.println(Math.max(3, 7)); // 두 값 중 최댓값
System.out.println(Math.random()); // 0.0과 1.0 사이의 랜덤값
}
}
10
7
0.40910432549890663
Math 클래스에 있는 abs(), max(), random() 등의 메소드가 바로 '클래스 메소드'
-main 메소드
public static void main(String[] args) {
...
}
-클래스 변수를 다룰 때
public class Counter {
static int count;
public static void increment() {
count++;
}
public static void main(String[] args) {
System.out.println(Counter.count);
Counter.increment();
System.out.println(Counter.count);
Counter.increment();
System.out.println(Counter.count);
Counter.increment();
System.out.println(Counter.count);
}
}
0
1
2
3
언제 클래스 메소드를 쓰나?
-> 생성된 인스턴스가 하나도 없더라도 메소드를 호출하고 싶다면 -> static메소드 사용
httpClient는 아파치 재단에서 URL 클래스를 훨씬 좋게 만든 것 (HTTP 프로토콜로 요청/ 응답 수행 가능)
안드로이드 OS에도 표준탑재되어 서버에서 정보를 다운받는 용도로 사용한다.
public class Test127{
public static void main(String[] args) throws IOException{
//CloseableHttpCilent : 실제로 요청 / 응답을 수행하는 핵심
CloseableHttpClient httpClient = HttpClients.createDefault();
String l = "http://192.168.2.11:8081/study3/Test126.jsp?pw=1234";
HttpGet httpGet = new HttpGet(l); //get 방식요청
httpGet.addHeader("User-Agent", "Mozila/5.0"); //헤더 조작 여지
// execute 실제로 요청/응답을 수행한다. httpResponse가 응답이다
CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
int resCode = httpResponse.getStatusLine().getStatusCode();
if(resCode == 200) {
InputStream in = httpResponse.getEntity().getContent();
BufferedReader bin = new BufferedReader(new InputStreamReader(in));
// new InputStremReader(in, "utf-8") 한글 깨지면 이거 써라...
BufferedReader bin = new BufferedReader(new InputStreamReader(in));
// new InputStremReader(in, "utf-8") 한글 깨지면 이거 써라… **
// why? => java default unicode / web default utf-8
String str = null;
while((str=bin.readLine())!=null){
System.out.println(str);
}
}
}
}
우리는 지금 Get 방식으로 사용하는 법을 배웠다. 많은 정보를 서버에서 다운받는 것에는 차이가 없다 GET이 든 POST든 Client에서 대량의 정보를 업로드 하려면 POST를 써야함 ** 위 코드와 많이 틀려지게 되니 이 점 유의할것 BufferedReader bin = new BufferedReader(new InputStreamReader(in)); ** new InputStremReader(in, "utf-8") 한글 깨지면 이거 써라… **
commons-logging.jar log4j-1.2.17.jar 은 lib 폴더에 넣는다.
%m%n 만 해도 됨ㅎㅎ [시간] INFO about : HelloWorld 이런 식으로 뜸
로그 파일의 형식 지정 : 단순히 콘솔에 찍어보는 걸 넘어서 내부적인 동작을 고스란히 담아낼 수 있다.
로그파일 분석 툴을 이용하면 사이트 전반의 분석을 가능하게 한다.
3. 실전에는 Util.L(…) 같은 거 만들어서 쓰는 경우가 많다.
pageNavigation
페이지 개수 = ((글 갯수 -1) / 페이지 크기 ) + 1
블럭 사이즈 (BS) : 10 단위로 하단에 보여짐
이전 페이지 : (BB!=1)
다음 페이지 : (BE != 총 페이지 수)
BB = ((CP -1)/ 10) * 10 +1 : 처음 보여줄 1 2 3 4 5 개 / CP 는 1 2 3 4 5 .. 들 중 하나
1. 정렬된 순서 보기
SELECT id, title FROM Temp10T ORDER BY id DESC;
2. rownum??
SELECT id, rownum FROM Temp10T;
SELECT id, rownum FROM Temp10T ORDER BY id DESC;
—row num은 order by 이전에 부여된다. 따라서 order by 이후에 rownum으로 쪼개는 건 무의미
— 그러면 orderby 시켜놓고 그 다음에 rownum 붙이겠다?
SELECT id, rownum FROM ( SELECT id FROM Temp10T ORDER BY id DESC );
3. rownum을 기준으로 페이지 나누기?
SELECT id, rownum FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) WHERE rownum > 0 AND rownum <= 5;
SELECT id, rownum FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) WHERE rownum > 5 AND rownum <= 10;
Rownum 이 10까지 없고 모자란다? 5개 가져오는 중에 5~10 사이가 없음 안됨
4. rownum을 field로 굳혀놓고 나누기!!
SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T ORDER BY id DESC );
SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) ) WHERE sq > 0 AND sq <= 5; SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) ) WHERE sq > 5 AND sq <= 10;
5. 서브쿼리로 정리해서 깔끔하게!!
SELECT * FROM Temp10T WHERE id IN ( SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) ) WHERE sq > 10 AND sq <= 20 ) ORDER BY id DESC;
select * from (select id, rownum as sq from (select id from temp10t where 0=0 order by id desc))
where sq>20 and sq<=30;
6. 나중의 검색을 위해서 0 = 0 은 그냥 끼워 넣어준다(검색을 어떻게 할지 생각해 보자)
SELECT * FROM Temp10T WHERE id IN ( SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T WHERE 0 = 0 ORDER BY id DESC ) ) WHERE sq > 5 AND sq <= 10 ) ORDER BY id DESC;
여기에서 0 = 0 을 응용하여 검색기능에서의 나누기 시도한다.
StringBuffer find = new StringBuffer(" WHERE 0 = 0"); if( title != null ){ find.append(" AND title LIKE '%"); find.append( title ); find.append("%'"); } if( user != null ){ find.append(" AND user ='"); find.append( title ); find.append("'"); } if( content != null ){ find.append(" AND content LIKE '%"); find.append( content ); find.append("%'"); }
String subSql = "SELECT id FROM " + "( SELECT id, rownum as sq FROM " + "( SELECT id FROM Temp10T "+ find.toString() + " ORDER BY id DESC ) )" + "WHERE sq > 5 AND sq <= 10";
String countSql = "SELECT COUNT(*) FROM Temp10T " + find.toString(); String sql = "SELECT * FROM ("+ subSql +") ORDER BY id DESC";
그러면 아래와 같은 형태의 결과를 보게 될 것이다.
SELECT COUNT(*) FROM Temp10T WHERE 0 = 0 AND user = 'root' AND content LIKE '%ab%'
....
SELECT * FROM Temp10T WHERE id IN ( SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T WHERE 0 = 0 AND user = 'root' AND content LIKE '%ab%' ORDER BY id DESC ) ) WHERE sq > 0 AND sq <= 3 ) ORDER BY id DESC;
0=0 위치가 검색 조건이 들어갈 위치
select * from temp10t where id in(select id from (select id, rownum sq from (select id from temp10t where title like '%bc%' order by id desc))where sq>0 and sq<=10) order by id desc;
Mysql
create table Temp10t(
-> id integer(3),
-> title varchar(7));
~insert로 입력
select * from temp10t order by id desc limit 0, 10;
10 씩 쪼개줌
select * from temp10t order by id desc limit 10, 10;
10개 세고 또 10개
> form-group으로 지정된 div를 이용하여 label과 input을 한쌍으로 묶어서 보여준다
함수의 매개변수의 갯수가 틀려도 호출된다. 만일 갯수가 틀리면 앞의 변수부터 대입이 된다.
변수 선언시에는 var라는 키워드를 사용한다. 변수는 모든 값이 대입 가능 (정수, 문자열, 실수, 함수, 객체...)
두번 선언해도 에러 안나고, var없이 선언해도 에러 안난다
script 태그 안에 있는 코드는 페이지가 모두 로딩 되지 않은 상태에서 호출 변수를 선언하지 않고 사용하면 초기값은 undefined이고 여난이 불가능하다.
var total=0; 코드가 빠졌을 때 에러가 나는 이유를 점검하자.
java는 블럭 안에서 선언한 변수는 블럭에서만 쓸 수 있는 개념인데 javascript는 선언만 되어 있으면 쓸 수 있고, 선언 안해도 쓴다
모든 html 요소는 id 속성을 가질 수 있다
속성 값은 pk처럼 겹치면 안된다
Document.getElementById("abcd") : id 값으로 객체의 포인터를 찾는다
window.onload = function(){
var op = document.getElementById("abcd");
op.onclick = function () {
alert();
}
}
/*op라는 포인터 변수로 해당 객체를 가리킨다
포인터를 통해 객체가 가진 속성을 읽고, 조작할 수 있다
op.onclick은 op 포인터가 가리키는 객체의 onclick 이라는 변수(프로퍼티)
javascript 변수는 다 가리킬 수 있다.
onclick은 이름없는 함수와 다름 없다.
가리키는 것과 호출하는 것은 다르다(여기서는 가리키기만 한다.)
호출되는 시점?
op 가리키는 객체에 click 상황이 벌어지면 onclick 이 가리키는 함수가 호출된다.
이벤트 처리의 두가지 방법
1. onXXX 속성을 이용하는 방법 : onclick="alert();"
2. onXXX 속성을 함수포인터로 쓰는 방법 : 위 코드의 방법.(이 방법이 더 많이 스임).*/
window.onload = function(){
var is = document.getElementsByTagName("img");
for(var i=0;i<is.length;i++){
alert(is[i].src);
}
}
/*ls[0] = function(){alter(i)} 가리키는 시점에서는 i가 0인데, 호출하는 시점에서는 4가 된다
가리키는 시점의 값과 호출하는 시점의 값이 같아야 한다
=> 함수의 매개변수를 활용한 로컬변수를 사용해야한다*/
package mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Controller {
public String handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception;
}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
public String value();
}
package mvc;
//import 생략~
public class DispatcherServlet extends HttpServlet {
private Map<String, Controller> map = null;
@Override
public void init(ServletConfig config) throws ServletException{
map = new Hashtable<String, Controller>();
String cs = "mvc.CtrlList,mvc.CtrlAdd2";
for(String str : cs.split(",")){
try{
//해당 클래스 가져오고
Class<?> cls = Class.forName(str);
//RequestMapping에서 지정된 url 패턴 따오고
RequestMapping an = cls.getAnnotation(RequestMapping.class);
//얘 때문에 Controller에너는 Annotation!
System.out.println("this is an : " + an);
//해당 controller instance 받아오고
Controller value = (Controller) cls.newInstance();
// 이름이 str인 Controller 클래스 찾기
// url 따기
String key = an.value();
//url-pattern과 controller 매핑
map.put(key, value);
}catch (Exception e) {}
} //String[] cs2 = cs.split(","); for(int i=0;i<cs2.length;i++)
System.out.println(map.toString());
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse
response)
throws IOException, ServletException {
}
}
package mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RequestMapping("/apple_list.do")
public class CtrlList implements Controller {
@Override
public String handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return null;
}
package mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RequestMapping("/apple_add2.do")
public class CtrlAdd2 implements Controller{
@Override
public String handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return null;
}
}
JSP MODEL1 / MVC MODEL2
<model1>
가장먼저 들어오는 곳이 JSP이다.
JSP에서 비즈니스 로직, VIEW모든 것을 처리한다.
<model2>
가장먼저 요청하는 곳이 서브릿단이다.
비즈니스 로직을 처리하는 서블릿을 완전히 분리시켜서 VIEW단과 로직을 처리하는 단을 분리시킨다.
Controller 추가해야할 때
<servlet>
<servlet-name>abcd2</servlet-name>
<servlet-class>mvc.DispatcherServlet</servlet-class>
<init-param>
<param-name>controllers</param-name>
<param-value>
mvc.CtrlList,
mvc.CtrlAdd2
</param-value>
</init-param>
</servlet>
<!-- 여기 이렇게 controller를 추가하면 되지 않을까! -->
public void init(ServletConfig config) throws ServletException{
map = new Hashtable<String, Controller>();
String cs = config.getInitParameter("controllers");
HTML 소스 긁어오는애
package main;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
public class Test126 {
public static void main(String[] args) throws Exception{
URL rl = new URL("http://localhost:8081/0802/apple_list.do");
URLConnection ucon = rl.openConnection();
InputStream in = ucon.getInputStream();
BufferedReader bin = new BufferedReader(new InputStreamReader(in,
"UTF-8")); //>> char 단위로 읽게해주는 adapter
//사실 UTF-8 빼도 되더라 얜 응답 내용
String l = null;
while((l = bin.readLine()) !=null){
System.out.println(l);
}
in.close();
}
}
java.net.URL은 이것 자체가 작은 웹브라우저의 역할을 한다. 요청을 날리고 그에 해당하는 응답을 받아들인 다 안드로이드 앱에서 버튼을 누르면 오늘의 배송정보가 넘어오는 ? 배송정보는 서버에 올라와 있는 상태! => 이 다운 받는 역할, 서버에 존재하는 배송정보를 다운받는 역할을 수행한다. 소켓으로 다 짜는 것이 아니라 http 프 로토콜로 서버와 통신할 때는 이 클래스를 주로 이용한다. 소켓으로 다 짜는 것이 아니라 http 프로토콜로 서버와 통신할 때는 이 클래스를 주로 이용한다. 앱 같은 경우에서 서버로부터 많은 데이터를 다운 받아야 할 경우에 URL 클래스를 이용하여 jsp 파일로부터 정 보를 다운받는다 이게 워낙 많이 쓰이다 보니 이를 강화한 오픈 소스 라이브러리가 등장 = apache http client 프로젝트 = 안 드로이드의 http 기반 표준 통신 수단
암호가 맞으면 다운, 아니면 안됨
<%@ page contentType="text/plain; charset=UTF-8" pageEncoding="EUC-KR" %><%
String pw = request.getParameter("pw");
if(pw.equals("1234")){
String[] l = {"사과", "귤", "배", "토마토"};
String nl = "\r\n"; //줄 바꿈 표시
for (int i = 0; i < l.length; i++) {%>
<%=l[i]%><%=nl%>
<%}}else{%>
암호틀림
<%}%>
public static void main(String[] args) throws Exception{
URL rl = new URL("http://localhost:8081/0802/Test126.jsp?pw=1230");
URLConnection ucon = rl.openConnection();
InputStream in = ucon.getInputStream();
BufferedReader bin = new BufferedReader(new InputStreamReader(in, "UTF8")); //>> char 단위로 읽게해주는 adapter
//사실 UTF-8 빼도 되더라 얜 응답 내용
String l = null;
while((l = bin.readLine()) !=null){
System.out.println(l);
}
in.close();
}
SQL> create table temp20t( 2 data char(3) null 3 );
테이블이 생성되었습니다.
SQL> insert into temp20t values('abc');
1 개의 행이 만들어졌습니다.
SQL> insert into temp20t values(null);
1 개의 행이 만들어졌습니다.
Q. NULL 4글자가 입력 가능? null은 빈값을 의미
insert into temp20t values('null'); -> null과 'null'은 구분하자
% select * from temp20t where data = null; NO
select * from temp20t where data is null; YES
(null 과의 비교는 is를 이용한다)
<문제점>
package main;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class Test110 {
public static void main(String[] args) throws Exception {
String data = "xyz";
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
//sql 이어 붙일 땐 ''에 주의해야한다
//data에 null 일 때는 에러 -> 왜? null이라는 문자열이 들어가는 것으로 됨
//나름 해결책 이지만 null 가능 필드가 2개면 경우의 수가 4개 / 3개면 8개
//이런 문제 떄문에 현업에서는 PreparedStatement를 더 선호한다.
//현업에서는 아예 char 는 무조건 4자리 이상을 잡게 하는 경우도 있다.
String sql =(data != null) ?
"insert into temp20t values ('"+data+"')":
"insert into temp20t values(null)";
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql);
stmt.close();
conn.close();
}
}
<해결책>
package main;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test111 {
public static void main(String[] args) throws Exception {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
/*Statement 가 어떤 sql 문장이든 실행하는 범용적인데 반해서
* preparedStatement 는 생성시에 준비한 그 문장만 실행 할 수 있다
* 대신 ? 영역을 setString , setInteger등을 이용하여 채울 수 있다
* (순서가 1부터 시작하는 것에 주의)
* execute 시에 매개변수 없음에 주의*/
String sql = "insert into temp20t values(?)";
PreparedStatement stmt = conn.prepareStatement(sql); //sql문장 전용의 바구니
// stmt.setString(1,"LEE");
stmt.setString(1, null);//에러 안남 null값이 들어간 행이 생김
//이걸 쓰면 null 값을 넣을 때 ''를 붙여야 할지를 결정하기 위해 이런저런 고민 할 필요가 없어진다(위의 코드처럼)
stmt.executeUpdate();
stmt.close();
conn.close();
}
}
/*SQL> select * from temp20t;
DATA
------
abc
xyz
xyz
xyz
LEE -> 컴파일 시 들어감*/
AUTOBOXING / UNBOXING
package main;
public class Test112 {
//매개변수로 String 을 0..*개를 넣어도 에러가 안나는 선언 방식
public static void test2(Object...args){
for(int i = 0; i < args.length; i++){
if(args[i] == null){
System.out.println("null");
}else if(args[i] instanceof Integer){
int r = ((Integer)args[i]).intValue();
System.out.println("null");
}else if(args[i] instanceof Double){
double r = ((Double)args[i]).doubleValue();
System.out.println(r+0.1);
}else if(args[i] instanceof String){
System.out.println((String)args[i]);
}
}
}
public static void test(String... args){
System.out.println(args.length);
}
//Object arg_1 = 100; -> 100을 new Integer(100)로 자동변환
//Object arg_3 = 3.14; => 3.14를 new Double(3.14)로 자동변환
public static void main(String[] args){
test2(100, "Hello", 3.14, null);
test("apple");
test();
test("apple", "banana");
}
}
/*autoboxing unboxing
*
* Object i = 100;(o)
* int i = j;(x)
*
* Integer i = 100(o)
* int j = i;(o)*/
<프레임워크 만들기>
package main;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test113 {
public static int update(String sql, Object... args) throws Exception{
int rc = 0;
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
PreparedStatement stmt = conn.prepareStatement(sql); //sql문장 전용의 바구니
for(int i = 0; i < args.length; i++){
if(args[i] == null){
stmt.setObject(i+1, null);
}else if(args[i] instanceof Integer){
int r = ((Integer)args[i]).intValue();
stmt.setInt(i+1, r);
}else if(args[i] instanceof Double){
double r = ((Double)args[i]).doubleValue();
stmt.setDouble(i+1, r);
}else if(args[i] instanceof String){
stmt.setString(i+1, (String)args[i]);
}
}
rc = stmt.executeUpdate();
stmt.close();
conn.close();
return rc;
}
public static void main(String[] args) throws Exception{
String sql = "insert into temp20t values(?,?)";
update(sql, "KIM",100);
}
}
/*프레임워크 만들기 */
<Anonymous class>
package main;
interface ITemp{
public void print();//인스턴스 못만듬 , abstract 클래스이기 떄문에
//클래스 : 참조형변수 선언/ 인스턴스 생성 / 상속해서 인스턴스 선언
}
public class Test114 {
public static void main(String[] args){
/*Anonymous class : 이름 없는 클래스
* -> 조상은 있음 : ITemp
* ITemp를 상속받고 -> 모든 메소드 오버라이딩 해주고
* 이름이 없어서 재사용은 불가능하다
* -클래스 선언하고 , 인스턴스 생성하고는 끝
* t가 왜 가리킬 수 있는 거지? A t = new B() 자손이 조상에서 오버라이딩한 것을 가져올 수 있기 때문에 */
final int i = 100; //i = 로컬변수다 -> final로 선언해주면 어나니머스 클래스에서 사용할 수 있음 / 객체 지향 개념
ITemp t = new ITemp(){
public void print(){
System.out.println("HelloWorld" + i);
}
};
t.print();//자손 인스턴스가 소환
}
}
JSP 기본 문법
JSP 페이지
<%-- JSP 주석 --%>
<% 스클립틀릿(자바 명령문) %> -> 웹 서버 쪽 실행
<%= 익스프레션 %> -> 자바식 (연산자 포함식, 메서드 호출식) -> 웹 서버 쪽 실행 => 웹 브라우저로 실행
${ 익스프레션 랭귀지 } - 빠른 간단한 연산 가능
<HTML>
<BODY>
<% int total = 0;
for(int cnt = 0; cnt <= 100; cnt++)
total += cnt;
%> //스클립틀릿 -> 자바 명령문
<%= total %> //익스프레션 -> 자바식(연산자 포함식, 메서드 호출식)
</BODY>
</HTML>
서블릿 클래스
서블릿 클래스 골격 선언 -> service 함수 메서드 선언 -> 명령 -> 파일로 텍스트 출력
//서블릿 클래스 골격 선언
public class Servlet extends HttpServlet{
//service 함수 메서드 선언
public void service(HttpServletRequest request, HttpServletResponse response)
throws IOException ServletException{
//명령
for(int cnt = 1; cnt <= 100; cnt++)
total += cnt;
//파일로 텍스트 출력
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<BODY>");
out.println("%d",total);
out.println("</BODY>");
out.println("</HTML>");
}
}
<web.xml> 에 서블릿 등록
<servlet>
<servlet-name>Servlet-test</servlet-name>
<servlet-class>servlet</servlet-class>
</servlet> //서블릿 클래스 이름이 들어감
<servlet-mapping>
<servlet-name>servlet-test</servlet-name>
<url-pattern>/servlet</url-pattern>
</servlet-mapping> //서블릿 클래스 호출할 때 사용할 URL 들어감
<쿠키 : 웹 브라우저 쪽에서 데이터 입력, 수정, 삭제, 조회 >
-> 결제 모듈에서 사용 / A, B, C 서블릿이 각자 있고 각자의 유저가 쿠키를 생성하여 따로 저장할 수 있음 (장바구니 , 로그인 정보에 사용)
package study3;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*http://localhost:8081/study3/state?use=readCookie
* 요청 -> 응답, 요청의 방법이 두가지 get / post // get : 엽서 / post : 택배
*
* 엽서와 주소의 내용을 구분하는 선의 역할 : ?
* ? 오른쪽 내용 : key=value 형태로 구성
* request.getParameter를 이용하여 추출할 수 있따
* 거의 대부분이 get방식이고 form 에서 method = "POST"로 지정된 경우만 POST방식*/
public class StateServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String use = request.getParameter("use");
if("addCookie".equals(use)){
Cookie ck = new Cookie("name", "apple");
response.addCookie(ck);
}else if("readCookie".equals(use)){
Cookie[] cks = request.getCookies();
if(cks != null){
for(int i = 0; i < cks.length; i++){
String l = cks[i].getName() + ","+ cks[i].getValue();
System.out.println(l);
}
}else{
System.out.println("Cookie is null");
}
}
System.out.println(use);
}
//addcookie 후 read 쿠키를 하니
/*Cookie is null
readCookie
getCookie
/*쿠키는 서블렛과 다르게 브라우저에서 생성 -> 서버에서 알 수 있는 방법은 응답이 넘어갈 때(addCookie -> response 멤버 변수)
*요청할 때 쿠키를 물고온다 / 응답 내보낼때만 서블릿이 조작할 수 있음
*/
}
세션사용
최초 getSession() 호출시에는 고유 넘버가 없이 요청이 들어온다 * 기억장소 생성 - Map<String, Object> 형태 * 고유 넘버 생성 * JSESSIONID 키 값으로 고유 넘버를 쿠키에 저장 * * 그 이후에 getSession() 호출 : 고유 넘버 물고 왔으니 그걸로 기억장소 찾는다 * "브라우저 마다 개별적인 기억장소가 생성된다"
package study3;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
//session으로 접근 가능하게 만드세요
// http://localhost:8081/study3/state?use=readCookie
public class SessionServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
System.out.println( session.isNew() );
//true
//JSESSIONID,2C7E8E0D95817C0E56780B2B4644924D
session.setAttribute("apple", "Object!!");
Object value = session.getAttribute("apple");
System.out.println(value.toString());
/*false
Object!!
*/
/*최초 getSession() 호출시에는 고유 넘버가 없이 요청이 들어온다
* 기억장소 생성 - Map<String, Object> 형태
* 고유 넘버 생성
* JSESSIONID 키 값으로 고유 넘버를 쿠키에 저장
*
* 그 이후에 getSession() 호출 : 고유 넘버 물고 왔으니 그걸로 기억장소 찾는다
*
* "브라우저 마다 개별적인 기억장소가 생성된다"*/
}
}
<jsp>
<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%> <%! int i = 0; %> <% int j = 0; %> http://www.w3.org/TR/html4/loose.dtd">
<%=i++ %> <%=j++ %>
<%-- jsp 주석 ,html 파일 요청하듯이 요청한다(web.xml 수정할 필요 없다) i = 멤버 변수 / j = 로컬 변수의 느낌이 난다 jsp 파일을 요청하면 톰캣은 이것을 *.java 파일로 변환한다(서블릿코드) 이것은 컴파일하고 인스턴스를 만들어 적재하고 인스턴스 재활용 한다
서블릿 이후에 asp의 등장으로 위기를 느낀 자바쪽에서 ASP 비슷하게 만든 게 JSP http://192.168.2.11:8081/study/Test115.jsp --%>
package study3;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class JSPServlet extends HttpServlet{
private ServletContext application = null;
//대표적인 함수 getRealPath
private ServletConfig config = null;
//적재된 서블릿의 시점을 가져오는 것이 init 함수
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
application = config.getServletContext();
}
/*--------------------------------------------------------------------------------
*<%! ... %> 은 여기에 온다
* int i = 0;
*-------------------------------------------------------------------*/
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
PrintWriter out = response.getWriter();
/*--------------------------------------------------
* <%....%>은 여기에 온다
* int j = 0;
* --------------------------------------------------*/
/*--------------------------------------------------
* <%=... %은 print()로 감싸서 나온다
* <%=i++ %>
* out.println(i++);
<%=j++ %>
out.println(j++);
Test115.jsp > 유사한 형태로 변환되고 컴파일되고 인스턴스 만들어지고 적재된 뒤에 실행한다
* --------------------------------------------------*/
out.flush();
out.close();
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<body>
<!-- input type = "file" : 파일을 서버로 업로드 할 때 사용
이때 반드시 enctype = "multipart/form-data" 을 사용한다
fileup 에 해당하는 서블릿은 cos.jar 파일의 MultipartRequest 를 이용하여 업로드를 처리하는 것이 일반적
-->
<form method = "POST" action = "fileup" enctype = "multipart/form-data">
<input type = "text" name = "title" size = "20">
<input type = "file" name = "apple">
<input type = "submit">
</form>
</body>
</html>
<fileUpServlet.jsp>
package study3;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;
import java.io.InputStream;
public class FileUpServlet extends HttpServlet{
private ServletContext application = null;
@Override
public void init(ServletConfig config) throws ServletException {
application = config.getServletContext();
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String l = process2(request);
System.out.println(l);
}
/*request : 요청 , 브라우저에서 서버로 전달하는 개념
* request.getInputStream() 은 브라우저에서 서버로 전달되는 내용을 볼 수 있다
* 이 내용을 재구성하는 기능이 cos.jar 파일의 MultipartRequest 이다.
* .*/
public String process(HttpServletRequest request) throws IOException{
byte[] buf = new byte[1024];
int len = 0;
StringBuffer sb = new StringBuffer();
InputStream in = request.getInputStream();
while((len = in.read(buf)) != -1){
sb.append(new String(buf, 0, len));
}
in.close();
return sb.toString();
}
public String process2(HttpServletRequest request) throws IOException{
//fileup 디렉터리의 실제 저장 위치(절대 경로) 값을 파악한다.
String path = application.getRealPath("/WEB-INF/fileup");
System.out.println(path);
//cos.jar에서 제공되는 클래스
//DefaultFileRenamePolicy : 이름이 겹칠 때 이름 바꿔서 올린다
//따라서 올릴 때 이름과 서버에 올려진 이름이 다를 수 있따.
MultipartRequest mpr = new MultipartRequest(
request, path, 1024*1024*20, "UTF-8",
new DefaultFileRenamePolicy());
//업로드한 원래 파일이름
String ofn = mpr.getOriginalFileName("apple");
//중첩될 경우 이름을 바꾸어 저장하는 이름
String fsn = mpr.getFilesystemName("apple");
System.out.println(ofn +","+ fsn);
//MultipartRequest 쓰면 request.getParameter 못쓴다.
// 대신 MultipartRequest 안의 getParameter 써야 한다.
// 한글 처리도 내부에서 해주더라 !! ( "UTF-8"로 설정해서
String title = mpr.getParameter("title");
System.out.print(title);
System.out.print(path);
return null;
}
}
package study3;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LikeServlet extends HttpServlet{
int i = 0;
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println(this.toString());
/*많은 사람들이 동시에 접속해도 동일한 문자열이 계속 찍힌다 -> 동일한 인스턴스가 재사용되고 있다.
* 메모리 관리에는 장점이다
* 한꺼번에 많이 들어와도 적게 메모리를 소모한다
* */
PrintWriter out = response.getWriter();
out.println("<html><body>");
/*왜 synchronized ?
* 동시 요청 시 여러개의 쓰레드가 하나의 서블릿 인스턴스를 사용할 수 있다.*/
synchronized(this){
i = i+1;
for(int i = 0 ; i < 20000; i ++){
out.println(this.i);
}
}
out.println("</body></html>");
out.flush();
out.close();
}
}
3.서블렛 여러 기능
<ConfigServlet.java>
package study3;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ConfigServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("service");
//컨텍스트 경로
String l = request.getContextPath();
System.out.println("getContextPath : " + l);
//ip 주소 다음 나오는 전체 경로
String m = request.getRequestURI();
System.out.println("getRequestURI : " + m);
//접속한 브라우저의 ip 주소값
String n = request.getRemoteAddr();
System.out.println("getRemoteAddr : " + n);
//접속한 브라우저와 운영체제 정보를 담은 문자열이 얻어진다
//이것을 이용하여 모바일로 접근한 건지 컴으로 접근 한 건지 알수 있고
//모바일용 화면과 컴용 화면을 구분하여 제공할 수 도 있다.
String o = request.getHeader("User-Agent");
System.out.println("User-Agent : " + o);
/*getContextPath : /study3
getRequestURI : /study3/config
getRemoteAddr : 0:0:0:0:0:0:0:1
User-Agent : Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like Gecko */
}
/*init
service
service
service
service -> 서블릿의 인스턴스는 재활용 된다.
인스턴스는 재활용을 위해 내부적으로 적재된다 => init
적재되는 시점에 호출되는 함수가 init - 최초 요청 시 에만 호출된다.*/
@Override
public void init(ServletConfig config) throws ServletException {
// String val = config.getInitParameter("apple");
// System.out.println(val);
/*WEB-INF 폴더의 절대 경로값을 얻어온다
* 브라우저가 접근 못하는 폴더가 업로드 파일을 놓기에 가장 적합
* 허락받고 (돈내고) 다운 받을 때 FileInputStream 으로 읽어 내보낸다
* FileInputStream : 절대 경로를 필요로한다
* getRealPath : 유용하게 쓰인다.*/
ServletContext application = config.getServletContext();
String path = application.getRealPath("/WEB-INF/");
System.out.println(path);
// System.out.println("init");
}
/*blabla
C:\workspace3\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\study3\WEB-INF\
service*/
}
<LikeServlet.java>
package study3;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LikeServlet extends HttpServlet{
int i = 0;
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println(this.toString());
/*많은 사람들이 동시에 접속해도 동일한 문자열이 계속 찍힌다 -> 동일한 인스턴스가 재사용되고 있다.
* 메모리 관리에는 장점이다
* 한꺼번에 많이 들어와도 적게 메모리를 소모한다
* */
PrintWriter out = response.getWriter();
out.println("<html><body>");
/*왜 synchronized ?
* 동시 요청 시 여러개의 쓰레드가 하나의 서블릿 인스턴스를 사용할 수 있다.*/
synchronized(this){
i = i+1;
for(int i = 0 ; i < 20000; i ++){
out.println(this.i);
}
}
out.println("</body></html>");
out.flush();
out.close();
}
}
public class BangMyungVO { public Integer getNo() { return no; } public void setNo(Integer no) { this.no = no; } public String getGul() { return gul; } public void setGul(String gul) { this.gul = gul; } public String getTheTime() { return theTime; } public void setTheTime(String theTime) { this.theTime = theTime; } private Integer no = null; private String gul = null; private String theTime = null; }
<test_01.html>
<!DOCTYPE html> <head> <body> test_01.html <!-- cellspacing="0" : 셀 간 간격 cellpadding="12" : 셀의 벽과 내용과의 간격 border="1" : 경계줄의 굵기 bgcolor="#ccddee" 배경색, 각각 16진수이고 앞 두자리 : red, 다음 두자리 : green, 마지막 두자리 : blue => RGB 값을 섞은 값 rowspan="3", colspan="2" : 엑셀에서의 셀 병합과 같은 개념 rowspan은 상하, colspan은 좌우 셀과 병합한다. <font size = "20px" face = "Impact">apple</font> : 브라우저에 깔린 글꼴만 가능 align ="left| center | right" : 내용물의 좌우 정렬 속성을 정한다 width : 셀의 폭을 결정함 같은 오와 열에 있는 것들은 자동으로 지정된 크기에 맞춰진다(일일이 모든 칸에 크기를 줄 필요가 없다) --> <table border="0" cellspacing="2" cellpadding="12"> <tr bgcolor="#aabbcc"> <td width = "400px" rowspan="2"><font size = "20px" face = "Impact">apple</font></td> <td width = "250px">banana</td> </tr> <tr> <td bgcolor="#ccddee">kiwi</td> </tr> <tr> <td colspan="2" bgcolor="#ccddee" align="center">kiwi</td> </tr> </table> </body> </html>