728x90

출처 : Spring Security part V : Security tags | DuyHai's Java Blog
Spring security authorize taglib with jstl variable if statement not working

UserDetails 구현

package com.iot.dao.domain;

import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

public class UserInfo implements UserDetails {

	// pk
	private String user_id;

	private String passwd;
	private int level;
	
	private Collection<? extends GrantedAuthority> authorities;

	public void setUser_id(String user_id) {
		this.user_id = user_id;
	}

	public String getUser_id() {
		return this.user_id;
	}

	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}

	public String getPasswd() {
		return this.passwd;
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {
		this.authorities = authorities;
	}

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return this.authorities;
	}

	@Override
	public String getPassword() {
		return this.passwd;
	}

	@Override
	public String getUsername() {
		return this.user_id;
	}

	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@Override
	public boolean isEnabled() {
		return true;
	}
}

UserDetailsService 구현

package com.iot.dao.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.iot.dao.domain.UserInfo;

@Service
public class AuthDetailsService implements UserDetailsService {

	@Autowired
	private UserInfoService userService;

	@Override
	public UserInfo loadUserByUsername(String user_id) throws UsernameNotFoundException {
		UserInfo userInfo = userService.selectUserInfo(user_id);

		//
		if (userInfo == null || userInfo.getDelete_yn().equals("Y")) {
			throw new UsernameNotFoundException("User details not found with this username: " + user_id);
		}

		String role = userInfo.getAuthority();

		List<GrantedAuthority> authList = getAuthorities(role);

		//
		userInfo.setAuthorities(authList);

		return userInfo;
	}

	private List<GrantedAuthority> getAuthorities(String role) {
		List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
		authList.add(new SimpleGrantedAuthority("ROLE_USER"));

		// 
		if (role != null && role.trim().length() > 0) {
			if (role.equals("A")) {
				authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
			} else if (role.equals("S")) {
				authList.add(new SimpleGrantedAuthority("ROLE_MBER_MANAGER"));
			}
		}

		return authList;
	}
}

***-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:security="http://www.springframework.org/schema/security"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
           http://www.springframework.org/schema/security
           http://www.springframework.org/schema/security/spring-security-3.2.xsd">

	<!-- 확장자를 이용해 패턴을 걸때는 /**/*.해당 확장자 로 할 것(Ant Pattern 규칙) -->
	<security:http pattern="/**/*.js" security="none" />
	<security:http pattern="/**/*.css" security="none" />
	<security:http pattern="/images/*" security="none" />
	<security:http pattern="/login.iot" security="none" />

	<bean id="userService" class="com.iot.dao.service.AuthDetailsService" />

	<security:http auto-config="true">
		<security:intercept-url pattern="/json.iot" access="ROLE_ANONYMOUS,ROLE_USER" />
		<security:intercept-url pattern="/**/*.iot" access="ROLE_USER" />
		<security:intercept-url pattern="/user_add_ajax.iot" access="ROLE_ANONYMOUS" />

		<security:intercept-url pattern="/loginfailed.iot" access="ROLE_ANONYMOUS" />
		<security:intercept-url pattern="/logout" access="ROLE_ANONYMOUS" />

		<security:form-login login-page="/login.iot" default-target-url="/iot/transinfo_list.iot" authentication-failure-url="/loginfailed.iot" />
		<security:logout logout-success-url="/login.iot" />
		<security:access-denied-handler error-page="/loginfailed.iot" />

		<security:logout logout-url="/logout" success-handler-ref="/login.iot" />
	</security:http>

	<security:authentication-manager>
		<security:authentication-provider user-service-ref="userService" />
		<security:authentication-provider>
			<security:jdbc-user-service
				data-source-ref="dataSource"
				users-by-username-query="select user_id username, passwd, 1 as enabled from user_info where user_id = ? and delete_yn = 'N'"
				authorities-by-username-query="select name username, 'ROLE_USER' authority from user_info where user_id = ? and delete_yn = 'N'" />
		</security:authentication-provider>
	</security:authentication-manager>

</beans>

JSP

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

<sec:authentication property="principal.level" var="user_level"/>
${user_level}

<li class="dropdown">
	<a href="javascript:;" class="dropdown-toggle">사용자관리 <b class="caret"></b></a>
	<ul class="dropdown-menu">
		<c:if test="${user_level == 1}">
			<li class=""><a href="<c:url value="/car/user_list.car"/>">사용자관리</a></li>
		</c:if>
		<li><a href="<c:url value="/car/user_info.car"/>">내 정보</a></li>
		<li><a href="<c:url value="/logout"/>">로그아웃</a></li>
	</ul>
</li>
728x90
728x90

Spring MVC - 네이버 로그인 처리

네이버 로그인 API를 이용해서 네이버 계정으로 로그인 처리를 Spring 프레임웍에서 사용 할 수 있도록 간단하게 NaverLoginController를 작성해보았습니다. 임시로 로그인 결과값을 가지고 와서 tbluser2 테이블의 abcd 계정의 1111 암호를 사용하는 사용자로 로그인 되도록 고정했습니다. (authentication-provider 사용자가 제어 하는 부분은 따로 찾아서 적용필요)

bluexmas-security.xml

alias의 authenticationManager 이름은 NaverLoginController 에서 속성으로 사용

	<security:authentication-manager alias="authenticationManager">
		<security:authentication-provider>

			<security:jdbc-user-service
				data-source-ref="dataSource"
				users-by-username-query="select user_id username, pass password, 1 as enabled from tbluser2 where user_id = ?"
				authorities-by-username-query="select user_id username, 'ROLE_USER' authority from tbluser2 where user_id = ?" />

		</security:authentication-provider>
	</security:authentication-manager>

NaverLogInController.java

package com.bluexmas.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.SecureRandom;
import java.util.HashMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

@Controller
public class NaverLogInController {
	
	private String naverClientId = "네이버API_Client_ID";
	
	private String naverClientSecret = "네이버API_Client_Secret";
	
	private String state = "";
	
	@Autowired
	@Qualifier("authenticationManager")
	protected AuthenticationManager authenticationManager;
	
	/**
	 * 네이버 로그인 요청
	 * 
	 * @param request
	 * @param uri
	 * @return
	 */
	@RequestMapping(value = "/naverLogin.do")
	public String makeNaverRequestStatement(
			HttpServletRequest request,
			@RequestParam(value = "uri", required = false) String uri) 
	{
		HashMap<String, String> naverUrl = this.makeRequestStatement(request, naverClientId);
		this.state = naverUrl.get("state");
		String returnUrl = request.getHeader("referer");
		
		return "redirect:" + naverUrl.get("url");
	}
	
	/**
	 * 네이버 로그인 요청에 대한 응답 처리
	 * 
	 * @param request
	 * @param response
	 * @param state
	 * @param code
	 * @param error
	 * @param error_description
	 * @return
	 */
	@RequestMapping(value = "/naverRequestKey.do")
	public String getNaverRequestKey(
			HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam("state") String state, 
			@RequestParam(value = "code", required = false) String code, 
			@RequestParam(value = "error", required = false) String error, 
			@RequestParam(value = "error_description", required = false) String error_description) 
	{
		HttpSession session = request.getSession();
		
		System.out.print("state = " + this.state + "="+  state + "/code = " + code + "/error = " + error + "/error_description = " + error_description);
		
		if (state.equals(this.state)) {
			session.setAttribute("isLoged", true);
		} else {
			session.setAttribute("isLoged", false);
			//System.out.println("state key값 불일치. 인증에러");
			return "redirect:/index.html";
		}
		
		// 네이버에 token_type, access_token 요청
		HashMap<String, String> result1 = this.getRequestKey(request, state, code, naverClientId, naverClientSecret);
		
		//
		String access_token = result1.get("access_token");
		String refresh_token = result1.get("refresh_token");
		String token_type = result1.get("token_type");
		
		System.out.println("access_token = " + access_token + "," + refresh_token + "," + token_type);

		// 사용자 정보 조회 요청
		HashMap<String, Object> result2 = this.requestUserInfo(token_type, access_token);
		System.out.println("result=" + result2);

		String email = (String)result2.get("email");
		
		if (email==null) {
			System.out.println("email = " + email);
			session.setAttribute("isLoged", false);
			return "redirect:/index.html";
		}
		
		String user_id = (String)result2.get("email");
		
		// 수동 로그인(spring security manual login) 처리
		try {
			// 
			UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken("abcd", "1111");
			
			// Authenticate the user
			Authentication authentication = authenticationManager.authenticate(authRequest);
			SecurityContext securityContext = SecurityContextHolder.getContext();
			securityContext.setAuthentication(authentication);
		} catch (Exception e) {
			e.printStackTrace();
			SecurityContextHolder.getContext().setAuthentication(null);
		}
		
		//return "redirect:" + returnUrl;
		return "redirect:/index.html";
	}
	
	/**
	 * 호스트이름 반환
	 * 
	 * @param request
	 * @return
	 */
	public static String getHostname(HttpServletRequest request) {
		String port_str = (request.getServerPort()==80 ? "" : ":" + request.getServerPort());
		return "http://" + request.getServerName() + port_str + request.getContextPath();
	}
	
	/**
	 * state 값 생성
	 * 
	 * @return
	 */
	public String generateState() {
		SecureRandom random = new SecureRandom();
		return new BigInteger(130, random).toString(32);
	}
	
	/**
	 * 네이버 로그인 요청 (Redirect URL 생성)
	 * 
	 * 1. redirect 생성 - 네이버 로그인 요청 완료 후 응답 받는 url 생성
	 * 2. state 생성 - Ramdom 함수로 생성
	 * 3. 요청 URL 생성 반환
	 * 
	 * @param request
	 * @param clientId
	 * @return
	 */
	private HashMap<String, String> makeRequestStatement(HttpServletRequest request, String clientId) {
		//String redirectUri = "http://127.0.0.1:8080/naverRequestKey.cmx";
		String redirectUri = getHostname(request) + "/naverRequestKey.do";
		String state = generateState();
		String url = "https://nid.naver.com/oauth2.0/authorize?" + "response_type=code&client_id=" + clientId + "&redirect_uri=" + redirectUri + "&state=" + state;
		
		HashMap<String, String> naverUrl = new HashMap<String, String>();
		naverUrl.put("state", state);
		naverUrl.put("url", url);
		return naverUrl;
	}
	
	/**
	 * 네이버에 token_type, access_token 요청(로그인 성공 이후)
	 * 
	 * @param request
	 * @param state
	 * @param code
	 * @param clientId
	 * @param naverClientSecret
	 * @return
	 */
	private HashMap<String, String> getRequestKey(HttpServletRequest request, String state, String code, String clientId, String naverClientSecret) {
		String naverUrl = "https://nid.naver.com/oauth2.0/token?client_id=" + clientId + "&client_secret=" + naverClientSecret + "&grant_type=authorization_code" + "&state=" + state + "&code=" + code;
		String naverJsonKey = "";// null로 하니까 null이 json에 포함이 됨.
		HashMap<String, String> result = new HashMap<String, String>();

		try {
			HttpURLConnection conn = (HttpURLConnection) new URL(naverUrl).openConnection();
			BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
			String input;
			while ((input = reader.readLine()) != null) {
				naverJsonKey += input;
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		try {
			JSONParser parser = new JSONParser();
			JSONObject jsonObject = (JSONObject) parser.parse(naverJsonKey);
			
			result.put("access_token", (String) jsonObject.get("access_token"));
			result.put("refresh_token", (String) jsonObject.get("refresh_token"));
			result.put("token_type", (String) jsonObject.get("token_type"));
			
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 네이버에 로그인 사용자의 정보 요청
	 * 
	 * @param token_type
	 * @param access_token
	 * @return
	 */
	public HashMap<String, Object> requestUserInfo(String token_type, String access_token) {
		
		String url = "https://apis.naver.com/nidlogin/nid/getUserProfile.xml";
		String naverResult = "";
		try {
			HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
			conn.setRequestMethod("GET");
			conn.setRequestProperty("Authorization", token_type + " " + access_token);
			BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
			String input;
			while ((input = reader.readLine()) != null) {
				naverResult += input;
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		HashMap<String, Object> result = new HashMap<String, Object>();

		try {
			InputSource is = new InputSource(new StringReader(naverResult));
			Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
			XPath xpath = XPathFactory.newInstance().newXPath();
			Node email = (Node) xpath.evaluate("//data/response/email", xml, XPathConstants.NODE);
			Node nickname = (Node) xpath.evaluate("//data/response/nickname", xml, XPathConstants.NODE);
			Node profile_image = (Node) xpath.evaluate("//data/response/profile_image", xml, XPathConstants.NODE);
			Node age = (Node) xpath.evaluate("//data/response/age", xml, XPathConstants.NODE);
			Node gender = (Node) xpath.evaluate("//data/response/gender", xml, XPathConstants.NODE);
			Node id = (Node) xpath.evaluate("//data/response/id", xml, XPathConstants.NODE);
			Node birthday = (Node) xpath.evaluate("//data/response/birthday", xml, XPathConstants.NODE);
			if (email!=null) result.put("email", email.getTextContent());
			if (nickname!=null) result.put("nickname", nickname.getTextContent());
			if (profile_image!=null) result.put("profile_image", profile_image.getTextContent());
			if (age!=null) result.put("age", age.getTextContent());
			if (gender!=null) result.put("gender", gender.getTextContent());
			if (id!=null) result.put("id", id.getTextContent());
			if (birthday!=null) result.put("birthday", birthday.getTextContent());

		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

}


728x90
728x90

Chart.js - Spring 연동

출처 : Chart.js - Spring 연동

JSONChartJS 클래스

package com.intel4.json;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.intel4.service.QuestionListService;
import com.intel4.util.BeanUtils;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class JSONChartJS extends JSONData {

	@Override
	public JSONObject getJSON(HttpServletRequest request, HttpServletResponse response) {

		String subcmd = request.getParameter("subcmd");
		JSONObject jobj_data = null;
		if (subcmd.equals("line")) {
			jobj_data = getAddData(request, response);
		}
		return jobj_data;
	}

	private JSONObject getAddData(HttpServletRequest request, HttpServletResponse response) {
		
		JSONArray datas = new JSONArray();
		
		JSONObject data1 = new JSONObject();
		data1.put("month", "1월");
		data1.put("pc", 100);
		data1.put("monitor", 80);
		datas.add(data1);
		JSONObject data2 = new JSONObject();
		data2.put("month", "2월");
		data2.put("pc", 80);
		data2.put("monitor", 70);
		datas.add(data2);
		JSONObject data3 = new JSONObject();
		data3.put("month", "3월");
		data3.put("pc", 70);
		data3.put("monitor", 60);
		datas.add(data3);
		JSONObject data4 = new JSONObject();
		data4.put("month", "4월");
		data4.put("pc", 90);
		data4.put("monitor", 100);
		datas.add(data4);
		JSONObject data5 = new JSONObject();
		data5.put("month", "5월");
		data5.put("pc", 40);
		data5.put("monitor", 110);
		datas.add(data5);
		
		JSONObject result = new JSONObject();
		result.put("datas", datas);
		
		return result;
	}
}

Line Chart

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!doctype html>
<html>

<head>
<title>Line Chart</title>
<script type="text/javascript" src="<c:url value="/resources/js/jquery-1.12.0.js"/>"></script>
<script type="text/javascript" src="<c:url value="/resources/chartjs/Chart.js"/>"></script>
<style>
canvas {
	-moz-user-select: none;
	-webkit-user-select: none;
	-ms-user-select: none;
}
</style>
</head>
<body>

<div style="width: 80%">
	<div>
		<canvas id="canvas" height="350" width="600"></canvas>
	</div>
</div>

<script>
var chartLabels = [];
var chartData1 = [];
var chartData2 = [];

var lineChartData = {
	labels : chartLabels,
	datasets : [ {
		label : "월별 PC 판매량",
		fillColor : "rgba(220,220,220,0.2)",
		strokeColor : "rgba(220,220,220,1)",
		pointColor : "rgba(220,220,220,1)",
		pointStrokeColor : "#fff",
		pointHighlightFill : "#fff",
		pointHighlightStroke : "rgba(220,220,220,1)",
		data : chartData1
	}, {
		label : "월별 모니터 판매량",
		fillColor : "rgba(151,187,205,0.2)",
		strokeColor : "rgba(151,187,205,1)",
		pointColor : "rgba(151,187,205,1)",
		pointStrokeColor : "#fff",
		pointHighlightFill : "#fff",
		pointHighlightStroke : "rgba(151,187,205,1)",
		data : chartData2
	} ]

}

function createChart() {
	var ctx = document.getElementById("canvas").getContext("2d");
	LineChartDemo = Chart.Line(ctx, {
		data : lineChartData,
		options : {
			scales : {
				yAxes : [ {
					ticks : {
						beginAtZero : true
					}
				} ]
			}
		}
	});
}

try {
	$.ajax({
		type : 'POST',
		url : "<c:url value="/json"/>",
		dataType : 'json',
		data : {
			cmd : 'chart',
			subcmd : 'line'
		},
		success : function(result) {

			$.each(result.datas, function(inx, obj) {
				chartLabels.push(obj.month);
				chartData1.push(obj.pc);
				chartData2.push(obj.monitor);

			});

			createChart();

		},
		error : function(XMLHttpRequest, textStatus, errorThrown) {
			alert('There is an error : method(group)에 에러가 있습니다.');
		}
	});

} catch (e) {
	alert(e);
}
</script>
</body>
</html>

실행결과

Bar Chart

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>


<script type="text/javascript" src="<c:url value="/resources/js/jquery-1.12.0.js"/>"></script>
<script type="text/javascript" src="<c:url value="/resources/chartjs/Chart.js"/>"></script>
<style>
canvas{
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
}
</style>


<body>
 <div style="width:80%">
        <div>
            <canvas id="canvas" height="350" width="600"></canvas>
        </div>
    </div>
<script>
var chartLabels = [];
var chartData1 = [];
var chartData2 = [];


var lineChartData = {
    labels : chartLabels,
    datasets : [
        {
            label: "월별 PC 판매량",
            fillColor : "rgba(220,220,220,0.2)",
            strokeColor : "rgba(220,220,220,1)",
            pointColor : "rgba(220,220,220,1)",
            pointStrokeColor : "#fff",
            pointHighlightFill : "#fff",
            pointHighlightStroke : "rgba(220,220,220,1)",
            data : chartData1 ,
            backgroundColor: [
                "#FF6384",
                "#4BC0C0",
                "#FFCE56",
                "#E7E9ED",
                "#36A2EB"
            ]
        },
        {
            label: "월별 모니터 판매량",
            fillColor : "rgba(151,187,205,0.2)",
            strokeColor : "rgba(151,187,205,1)",
            pointColor : "rgba(151,187,205,1)",
            pointStrokeColor : "#fff",
            pointHighlightFill : "#fff",
            pointHighlightStroke : "rgba(151,187,205,1)",
            data : chartData2,
            backgroundColor: [
                "#FF6384",
                "#4BC0C0",
                "#FFCE56",
                "#E7E9ED",
                "#36A2EB"
            ]
        }
    ]
 
}

function createChart(){
    var ctx = document.getElementById("canvas").getContext("2d");
    new Chart(ctx, {
        type: 'horizontalBar',
    	data: lineChartData,
    	options: {
            scales: {
            	xAxes: [{
                    ticks: {
                        beginAtZero:true
                    }
                }]
            }
        }
    });
}

try {
	$.ajax({
		type : 'POST',
		url : "<c:url value="/json"/>",
		dataType : 'json',
		data : {
			cmd : 'chart',
			subcmd : 'line'
		},
		success : function(result) {
		
			    $.each(result.datas, function(inx, obj) {
			        chartLabels.push(obj.month);
			        chartData1.push(obj.pc);
			        chartData2.push(obj.monitor);
			         
			    });
			     
			    createChart();
			
		},
		error : function(XMLHttpRequest, textStatus, errorThrown) {
			alert('There is an error : method(group)에 에러가 있습니다.');
		}
	});

} catch (e) {
	alert(e);
}

 
</script>

</body>

</html>

실행결과

Pie Chart

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!doctype html>
<html>

<head>
    <title>Pie Chart</title>
    <script type="text/javascript" src="<c:url value="/resources/js/jquery-1.12.0.js"/>"></script>
    <script type="text/javascript" src="<c:url value="/resources/chartjs/Chart.js"/>"></script>
    <style>
    canvas{
        -moz-user-select: none;
        -webkit-user-select: none;
        -ms-user-select: none;
    }
    </style>
</head>

<body>
 <div style="width:80%">
        <div>
            <canvas id="canvas" height="350" width="600"></canvas>
        </div>
    </div>
<script>
var chartLabels = [];
var chartData1 = [];
var chartData2 = [];


var PieChartData = {
    labels : chartLabels,
    datasets : [
        {
            label: "월별 PC 판매량",
            fillColor : "rgba(220,220,220,0.2)",
            strokeColor : "rgba(220,220,220,1)",
            pointColor : "rgba(220,220,220,1)",
            pointStrokeColor : "#fff",
            pointHighlightFill : "#fff",
            pointHighlightStroke : "rgba(220,220,220,1)",
            data : chartData1 ,
            backgroundColor: [
                "#FF6384",
                "#4BC0C0",
                "#FFCE56",
                "#E7E9ED",
                "#36A2EB"
            ]
        }
        
        /*,
        {
            label: "월별 모니터 판매량",
            fillColor : "rgba(151,187,205,0.2)",
            strokeColor : "rgba(151,187,205,1)",
            pointColor : "rgba(151,187,205,1)",
            pointStrokeColor : "#aff",
            pointHighlightFill : "#aff",
            pointHighlightStroke : "rgba(151,187,205,1)",
            data : chartData2,
            backgroundColor: [
                "#FF6384",
                "#4BC0C0",
                "#FFCE56",
                "#E7E9ED",
                "#36A2EB"
            ]
        }
        */
    ]
 
}
 
function createChart(){
    var ctx = document.getElementById("canvas").getContext("2d");
    new Chart(ctx, {
        type: 'pie',
    	data: PieChartData,
    	
        options: {
            responsive: true
        }
    });
}

try {
	$.ajax({
		type : 'POST',
		url : "<c:url value="/json"/>",
		dataType : 'json',
		data : {
			cmd : 'chart',
			subcmd : 'line'
		},
		success : function(result) {
		
			    $.each(result.datas, function(inx, obj) {
			        chartLabels.push(obj.month);
			        chartData1.push(obj.pc);
			        chartData2.push(obj.monitor);
			         
			    });
			     
			    createChart();
			
		},
		error : function(XMLHttpRequest, textStatus, errorThrown) {
			alert('There is an error : method(group)에 에러가 있습니다.');
		}
	});

} catch (e) {
	alert(e);
}

 
</script>

</body>

</html>

실행결과

728x90
728x90

기본 Form 데이터 전달

기본 Form 데이터 전달 JSP - /sample/form1.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<html>
<head>
<body>

<form action="<c:url value="/form/form1.do"/>" method="get">
	<input type="text" name="user_id">
	<input type="password" name="password">
	<input type="submit">
</form>

</body>
</html>

기본 Form 데이터 전달 Controller

@Controller
public class FormController {
	
	@RequestMapping(value = "/form/form1.do", method = RequestMethod.GET)
	public String form1(
			@RequestParam("user_id") String user_id, 
			@RequestParam("password") String password,
			ModelMap modelMap) throws Exception 
	{
		System.out.println("user_id = " + user_id + "/" + password);
		return "redirect:/sample/form1.jsp";
	}

파일 업로드 Form 데이터 전달

파일 업로드 Form 데이터 전달 JSP - /sample/form2.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<html>
<head>
<body>

<form action="<c:url value="/form/form2.do"/>" method="post" enctype="multipart/form-data">
	<input type="text" name="title"><br/>
	<input type="file" name="file1"><br/>
	<input type="file" name="file2"><br/>
	<input type="submit">
</form>

</body>
</html>

파일 업로드 Form 데이터 전달 Controller

@Controller
public class FormController {
	
	@RequestMapping(value = "/form/form2.do", method = RequestMethod.POST)
	public String form2(
			@RequestParam("title") String title, 
			@RequestParam("file1") MultipartFile file1, 
			@RequestParam("file2") MultipartFile file2, 
			ModelMap modelMap) 
	{
		System.out.println("title = " + title);
		
		String uuid_filename1 = fileWrite(file1);
		String uuid_filename2 = fileWrite(file2);
		
		System.out.println(uuid_filename1 + "/" + uuid_filename2);
		
		return "redirect:/sample/form2.jsp";
	}
	
	// 파일 저장 메소드
	private String fileWrite(MultipartFile uploadfile) {
		OutputStream out = null;
		String targetFilename = null;
		try {
			String filePath = "C:/test"; // 설정파일로 뺀다.
			
			// 파일명 얻기
			String fileName = uploadfile.getOriginalFilename();
			
			// 파일의 바이트 정보 얻기
			byte[] bytes = uploadfile.getBytes();
	
			String originalFilename = uploadfile.getOriginalFilename(); // 파일명
			
			// 파일 확장자 추출
			String fileExt = FileUtils.getFileExt(originalFilename);
	
			UUID uuid = UUID.randomUUID();
			targetFilename = uuid.toString() + "." + fileExt.toLowerCase();
	
			String fileFullPath = filePath + "/" + targetFilename; // 파일 전체 경로
			
			// 파일 객체 생성
			File file = new File(fileFullPath);
			// 상위 폴더 존재 여부 확인
			if (!file.getParentFile().exists()) {
				// 상위 폴더가 존재 하지 않는 경우 상위 폴더 생성
				file.getParentFile().mkdirs();
			}
			
			// 파일 아웃풋 스트림 생성
			out = new FileOutputStream(file);
			// 파일 아웃풋 스트림에 파일의 바이트 쓰기
			out.write(bytes);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try { if (out != null) { out.close(); } } catch (IOException e) { e.printStackTrace(); }
		}
		return targetFilename;
	}
}
728x90
728x90

Spring - Drag & Drop 파일 업로드

출처 : Husk's repository :: 드래그 앤 드롭 파일 업로드 스프링 예제

관련 라이브러리 추가

commons-io-2.4.jar
commons-fileupload-1.3.jar

WebContent\WEB-INF\iot-servlet.xml

	<!-- ========================= Multipart Form-Data Resolver ========================= -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- max upload size in bytes -->
		<property name="maxUploadSize" value="20971520" /> <!-- 20MB -->
		<!-- max size of file in memory (in bytes) -->
		<property name="maxInMemorySize" value="1048576" /> <!-- 1MB -->
	</bean>

업로드 jsp (WebContent\WEB-INF\jsp\dragdrop\fileUpload.jsp)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
    <head>
        <title>Test</title>
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.js"></script>
        <style>
            .dragAndDropDiv {
                border: 2px dashed #92AAB0;
                width: 650px;
                height: 200px;
                color: #92AAB0;
                text-align: center;
                vertical-align: middle;
                padding: 10px 0px 10px 10px;
                font-size:200%;
                display: table-cell;
            }
            .progressBar {
                width: 200px;
                height: 22px;
                border: 1px solid #ddd;
                border-radius: 5px; 
                overflow: hidden;
                display:inline-block;
                margin:0px 10px 5px 5px;
                vertical-align:top;
            }
              
            .progressBar div {
                height: 100%;
                color: #fff;
                text-align: right;
                line-height: 22px; /* same as #progressBar height if we want text middle aligned */
                width: 0;
                background-color: #0ba1b5; border-radius: 3px; 
            }
            .statusbar{
                border-top:1px solid #A9CCD1;
                min-height:25px;
                width:99%;
                padding:10px 10px 0px 10px;
                vertical-align:top;
            }
            .statusbar:nth-child(odd){
                background:#EBEFF0;
            }
            .filename{
                display:inline-block;
                vertical-align:top;
                width:250px;
            }
            .filesize{
                display:inline-block;
                vertical-align:top;
                color:#30693D;
                width:100px;
                margin-left:10px;
                margin-right:5px;
            }
            .abort{
                background-color:#A8352F;
                -moz-border-radius:4px;
                -webkit-border-radius:4px;
                border-radius:4px;display:inline-block;
                color:#fff;
                font-family:arial;font-size:13px;font-weight:normal;
                padding:4px 15px;
                cursor:pointer;
                vertical-align:top
            }
        </style>
        <script type="text/javascript">
            $(document).ready(function(){
                var objDragAndDrop = $(".dragAndDropDiv");
                 
                $(document).on("dragenter",".dragAndDropDiv",function(e){
                    e.stopPropagation();
                    e.preventDefault();
                    $(this).css('border', '2px solid #0B85A1');
                });
                $(document).on("dragover",".dragAndDropDiv",function(e){
                    e.stopPropagation();
                    e.preventDefault();
                });
                $(document).on("drop",".dragAndDropDiv",function(e){
                     
                    $(this).css('border', '2px dotted #0B85A1');
                    e.preventDefault();
                    var files = e.originalEvent.dataTransfer.files;
                 
                    handleFileUpload(files,objDragAndDrop);
                });
                 
                $(document).on('dragenter', function (e){
                    e.stopPropagation();
                    e.preventDefault();
                });
                $(document).on('dragover', function (e){
                  e.stopPropagation();
                  e.preventDefault();
                  objDragAndDrop.css('border', '2px dotted #0B85A1');
                });
                $(document).on('drop', function (e){
                    e.stopPropagation();
                    e.preventDefault();
                });
                 
                function handleFileUpload(files,obj)
                {
                   for (var i = 0; i < files.length; i++) 
                   {
                        var fd = new FormData();
                        fd.append('file', files[i]);
                  
                        var status = new createStatusbar(obj); //Using this we can set progress.
                        status.setFileNameSize(files[i].name,files[i].size);
                        sendFileToServer(fd,status);
                  
                   }
                }
                 
                var rowCount=0;
                function createStatusbar(obj){
                         
                    rowCount++;
                    var row="odd";
                    if(rowCount %2 ==0) row ="even";
                    this.statusbar = $("<div class='statusbar "+row+"'></div>");
                    this.filename = $("<div class='filename'></div>").appendTo(this.statusbar);
                    this.size = $("<div class='filesize'></div>").appendTo(this.statusbar);
                    this.progressBar = $("<div class='progressBar'><div></div></div>").appendTo(this.statusbar);
                    this.abort = $("<div class='abort'>중지</div>").appendTo(this.statusbar);
                     
                    obj.after(this.statusbar);
                  
                    this.setFileNameSize = function(name,size){
                        var sizeStr="";
                        var sizeKB = size/1024;
                        if(parseInt(sizeKB) > 1024){
                            var sizeMB = sizeKB/1024;
                            sizeStr = sizeMB.toFixed(2)+" MB";
                        }else{
                            sizeStr = sizeKB.toFixed(2)+" KB";
                        }
                  
                        this.filename.html(name);
                        this.size.html(sizeStr);
                    }
                     
                    this.setProgress = function(progress){       
                        var progressBarWidth =progress*this.progressBar.width()/ 100;  
                        this.progressBar.find('div').animate({ width: progressBarWidth }, 10).html(progress + "% ");
                        if(parseInt(progress) >= 100)
                        {
                            this.abort.hide();
                        }
                    }
                     
                    this.setAbort = function(jqxhr){
                        var sb = this.statusbar;
                        this.abort.click(function()
                        {
                            jqxhr.abort();
                            sb.hide();
                        });
                    }
                }
                 
                function sendFileToServer(formData,status)
                {
                    var uploadURL = "<c:url value="/dragdrop/fileUpload/post.iot"/>"; //Upload URL
                    var extraData ={}; //Extra Data.
                    var jqXHR=$.ajax({
                            xhr: function() {
                            var xhrobj = $.ajaxSettings.xhr();
                            if (xhrobj.upload) {
                                    xhrobj.upload.addEventListener('progress', function(event) {
                                        var percent = 0;
                                        var position = event.loaded || event.position;
                                        var total = event.total;
                                        if (event.lengthComputable) {
                                            percent = Math.ceil(position / total * 100);
                                        }
                                        //Set progress
                                        status.setProgress(percent);
                                    }, false);
                                }
                            return xhrobj;
                        },
                        url: uploadURL,
                        type: "POST",
                        contentType:false,
                        processData: false,
                        cache: false,
                        data: formData,
                        success: function(data){
                            status.setProgress(100);
                  
                            //$("#status1").append("File upload Done<br>");           
                        }
                    }); 
                  
                    status.setAbort(jqXHR);
                }
                 
            });
        </script>
    </head>
     
    <body>
        <div id="fileUpload" class="dragAndDropDiv">Drag & Drop Files Here</div>
    </body>
</html>

Controller

package com.iot.controller;

import java.io.File;
import java.util.Iterator;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

/**
 * Handles requests for the application home page.
 */

@Controller
public class FileUploadDragDropController {

	@RequestMapping(value = "/dragdrop/fileUpload.iot", method = RequestMethod.GET)
	public String dragAndDrop(Model model) {
		return "/dragdrop/fileUpload";
	}

	@RequestMapping(value = "/dragdrop/fileUpload/post.iot") // ajax에서 호출하는 부분
	@ResponseBody
	public String upload(MultipartHttpServletRequest multipartRequest) { // Multipart로
																																				// 받는다.

		Iterator<String> itr = multipartRequest.getFileNames();

		String filePath = "C:/test"; // 설정파일로 뺀다.

		while (itr.hasNext()) { // 받은 파일들을 모두 돌린다.

			/*
			 * 기존 주석처리 MultipartFile mpf = multipartRequest.getFile(itr.next());
			 * String originFileName = mpf.getOriginalFilename(); System.out.println(
			 * "FILE_INFO: "+originFileName); //받은 파일 리스트 출력'
			 */

			MultipartFile mpf = multipartRequest.getFile(itr.next());

			String originalFilename = mpf.getOriginalFilename(); // 파일명

			String fileFullPath = filePath + "/" + originalFilename; // 파일 전체 경로

			try {
				// 파일 저장
				mpf.transferTo(new File(fileFullPath)); // 파일저장 실제로는 service에서 처리

				System.out.println("originalFilename => " + originalFilename);
				System.out.println("fileFullPath => " + fileFullPath);

			} catch (Exception e) {
				System.out.println("postTempFile_ERROR======>" + fileFullPath);
				e.printStackTrace();
			}

		}

		return "success";
	}

}

업로드된 폴더 웹에서 접근하기

Tomcat 설정파일 server.xml에 <Context docBase="C:/test" path="/test" reloadable="true"/> 를 Host 테그 전에 추가

        <Context docBase="C:/test" path="/test" reloadable="true"/>
      </Host>
    </Engine>
  </Service>
</Server>

Spring - Drag & Drop 파일 업로드 (img_type, img_id 속성 추가)

한 페이지내에서 여러개의 파일 업로드를 구현하기 위해서 img_type, img_id 속성을 추가해서 여러개의 업로드가 발생하더라고 구분 할 수 있게 구현

html 페이지

<div class="dragAndDropDiv" img_type="uploadarea" img_id="1">
<div class="dragAndDropDiv" img_type="uploadarea" img_id="2">

파일 올려진 경우 이벤트에서 img_type, img_id 속성 가져오기 - javascript

	$(document).on("drop",".dragAndDropDiv",function(e){
		$(this).css('border', '2px dotted #0B85A1');
		e.preventDefault();
		var files = e.originalEvent.dataTransfer.files;
		
		// img_type, img_id 속성 가져오기
		var img_type = $(e.target).attr('img_type');
		var img_id = $(e.target).attr('img_id');
		
		handleFileUpload(img_type, img_id, files,objDragAndDrop);
	});

FormData 구성 img_type, img_id 포함 - javascript

	function handleFileUpload(img_type, img_id, files,obj) {
		for (var i = 0; i < files.length; i++) {
			var fd = new FormData();
			fd.append('img_type', img_type);
			fd.append('img_id', img_id);
			fd.append('file', files[i]);
			
			var status = undefined;
			//var status = new createStatusbar(obj); //Using this we can set progress.
			//status.setFileNameSize(files[i].name,files[i].size);
			sendFileToServer(fd,status);
		}
	}

업로드 완료 처리 - javascript

img_type이 request인 경우 img테그의 src 속성 값 변경 처리

function sendFileToServer(formData,status) {
	var uploadURL = "<c:url value="/dragdrop/fileUpload/post.do"/>"; //Upload URL

... 생략 ...

		data: formData,
		success: function(data) { // 업로드가 완료되면 호출되는 메소드
			if (status != undefined) {
				status.setProgress(100);
			}
			
			// 
			console.log('img_type = ' + data.img_type);
			console.log('img_id = ' + data.img_id);
			$.each(data.files, function(index, file) {
				console.log('filename = ' + file);
				
				if (data.img_type=='request') {
					var targetObj = $(".dragAndDropDiv[img_type='"+data.img_type+"'][img_id='"+data.img_id+"']");
					targetObj.attr('src', '/test/' + file);
					targetObj.attr('uuid', file);
				}
			});
		}
	});

javascript 전체

$(document).ready(function() {
	
	var objDragAndDrop = $(".dragAndDropDiv");
	   
	$(document).on("dragenter",".dragAndDropDiv",function(e){
		e.stopPropagation();
		e.preventDefault();
		$(this).css('border', '2px solid #0B85A1');
	});
	$(document).on("dragover",".dragAndDropDiv",function(e){
		e.stopPropagation();
		e.preventDefault();
	});
	$(document).on("drop",".dragAndDropDiv",function(e){
		$(this).css('border', '2px dotted #0B85A1');
		e.preventDefault();
		var files = e.originalEvent.dataTransfer.files;
		
		// img_type, img_id 속성 가져오기
		var img_type = $(e.target).attr('img_type');
		var img_id = $(e.target).attr('img_id');
		
		handleFileUpload(img_type, img_id, files,objDragAndDrop);
	});
	$(document).on('dragenter', function (e){
		e.stopPropagation();
		e.preventDefault();
	});
	$(document).on('dragover', function (e){
		e.stopPropagation();
		e.preventDefault();
		objDragAndDrop.css('border', '2px dotted #0B85A1');
	});
	$(document).on('drop', function (e){
		e.stopPropagation();
		e.preventDefault();
	});
	  
	function handleFileUpload(img_type, img_id, files,obj) {
		for (var i = 0; i < files.length; i++) {
			var fd = new FormData();
			fd.append('img_type', img_type);
			fd.append('img_id', img_id);
			fd.append('file', files[i]);
			
			var status = undefined;
			//var status = new createStatusbar(obj); //Using this we can set progress.
			//status.setFileNameSize(files[i].name,files[i].size);
			sendFileToServer(fd,status);
		}
	}
	  
	var rowCount=0;
	function createStatusbar(obj){
		
		rowCount++;
		var row="odd";
		if(rowCount %2 ==0) row ="even";
		this.statusbar = $("<div class='statusbar "+row+"'></div>");
		this.filename = $("<div class='filename'></div>").appendTo(this.statusbar);
		this.size = $("<div class='filesize'></div>").appendTo(this.statusbar);
		this.progressBar = $("<div class='progressBar'><div></div></div>").appendTo(this.statusbar);
		this.abort = $("<div class='abort'>중지</div>").appendTo(this.statusbar);
		
		obj.after(this.statusbar);
		
		this.setFileNameSize = function(name,size){
			var sizeStr="";
			var sizeKB = size/1024;
			if(parseInt(sizeKB) > 1024) {
				var sizeMB = sizeKB/1024;
				sizeStr = sizeMB.toFixed(2)+" MB";
			} else {
				sizeStr = sizeKB.toFixed(2)+" KB";
			}
			
			this.filename.html(name);
			this.size.html(sizeStr);
		}
		  
		this.setProgress = function(progress){      
			var progressBarWidth =progress*this.progressBar.width()/ 100; 
			this.progressBar.find('div').animate({ width: progressBarWidth }, 10).html(progress + "% ");
			if(parseInt(progress) >= 100) {
				this.abort.hide();
			}
		}
		  
		this.setAbort = function(jqxhr){
			var sb = this.statusbar;
			this.abort.click(function() {
				jqxhr.abort();
				sb.hide();
			});
		}
	}
	  
	function sendFileToServer(formData,status) {
		var uploadURL = "<c:url value="/dragdrop/fileUpload/post.do"/>"; //Upload URL
		var extraData ={}; //Extra Data.
		var jqXHR=$.ajax({
				xhr: function() {
				var xhrobj = $.ajaxSettings.xhr();
				if (xhrobj.upload) {
					xhrobj.upload.addEventListener('progress', function(event) {
						var percent = 0;
						var position = event.loaded || event.position;
						var total = event.total;
						if (event.lengthComputable) {
							percent = Math.ceil(position / total * 100);
						}
						//Set progress
						if (status != undefined) {
							status.setProgress(percent);
						}
					}, false);
				}
				return xhrobj;
			},
			url: uploadURL,
			type: "POST",
			dataType : 'json',
			contentType:false,
			processData: false,
			cache: false,
			data: formData,
			success: function(data) { // 업로드가 완료되면 호출되는 메소드
				if (status != undefined) {
					status.setProgress(100);
				}
				
				// 
				console.log('img_type = ' + data.img_type);
				console.log('img_id = ' + data.img_id);
				$.each(data.files, function(index, file) {
					console.log('filename = ' + file);
					
					if (data.img_type=='request') {
						var targetObj = $(".dragAndDropDiv[img_type='"+data.img_type+"'][img_id='"+data.img_id+"']");
						targetObj.attr('src', '/test/' + file);
						targetObj.attr('uuid', file);
					} else {
						var uploadTbody = $('#uploadTbody');
						var row = $('<span style="display : block;"></span>');
						row.text(file);
						uploadTbody.append(row);
						
						// 배열 초기화
						var uploadFilenames = new Array(9);
						for (i=0; i<uploadFilenames.length; i++) {
							uploadFilenames[i] = '';
						}
						var t_fileList = $('#uploadTbody>span');
						
						/*
						for (i=1; i<=t_fileList.length; i++) {
							var file_value = $('#uploadTbody>span:nth-child('+i+')');
							console.log(i + '/' + file_value.text());
							uploadFilenames[i-1] = file_value.text();
						}
						*/
						
						console.log(t_fileList.length);
						$.each( t_fileList, function( key, value ) {
							console.log( key + ": " + $(value).text() );
							uploadFilenames[key] = $(value).text();
						});
						
						console.log(uploadFilenames[0]);
						console.log(uploadFilenames[1]);
						console.log(uploadFilenames[2]);
						console.log(uploadFilenames[3]);
					}
				});
			
				//$("#status1").append("File upload Done<br>");          
			}
		});
		
		if (status != undefined) {
			status.setAbort(jqXHR);
		}
	}
});

업로드 메소드

	@RequestMapping(value = "/dragdrop/fileUpload/post.do") // ajax에서 호출하는 부분
	@ResponseBody
	public String upload(
			@RequestParam(value = "img_type", required = false, defaultValue = "") String img_type, 
			@RequestParam(value = "img_id", required = false, defaultValue = "-1") int img_id, 
			MultipartHttpServletRequest multipartRequest) // Multipart로 받는다.
	{ 

		System.out.println("img_type = " + img_type + "/img_id = " + img_id);

		Iterator<String> itr = multipartRequest.getFileNames();

		String filePath = "C:/test"; // 설정파일로 뺀다.
		String targetFilename = "";
		
		JSONArray filenames = new JSONArray();

		while (itr.hasNext()) { // 받은 파일들을 모두 돌린다.

			/*
			 * 기존 주석처리 MultipartFile mpf = multipartRequest.getFile(itr.next());
			 * String originFileName = mpf.getOrigin'alFilename(); System.out.println(
			 * "FILE_INFO: "+originFileName); //받은 파일 리스트 출력
			 */

			MultipartFile mpf = multipartRequest.getFile(itr.next());

			String originalFilename = mpf.getOriginalFilename(); // 파일명

			// 파일 확장자 추출
			String fileExt = FileUtils.getFileExt(originalFilename);

			UUID uuid = UUID.randomUUID();
			targetFilename = uuid.toString() + "." + fileExt.toLowerCase();

			String fileFullPath = filePath + "/" + targetFilename; // 파일 전체 경로

			try {
				// 파일 저장
				mpf.transferTo(new File(fileFullPath)); // 파일저장 실제로는 service에서 처리

				System.out.println("originalFilename => " + originalFilename);
				System.out.println("fileFullPath => " + fileFullPath);

			} catch (Exception e) {
				System.out.println("postTempFile_ERROR======>" + fileFullPath);
				e.printStackTrace();
			}
			
			filenames.add(targetFilename);

		}
		
		JSONObject jobj = new JSONObject();
		jobj.put("img_type", img_type);
		jobj.put("img_id", img_id);
		jobj.put("files", filenames);

		return jobj.toJSONString();
	}
728x90
728x90

댓글 테이블 생성

CREATE TABLE `main_board_reply` (
  `seq` int(11) NOT NULL AUTO_INCREMENT,
  `main_seq` int(11),
  `title` varchar(11) DEFAULT NULL,
  `name` varchar(11) DEFAULT NULL,
  `date` date DEFAULT NULL,
  `count` int(11) DEFAULT NULL,
  `content` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`seq`)
)

MainBoardReply 클래스 생성

package com.iot.db.domain;

import java.sql.Date;

import bluexmas.util.DateUtils;
import net.sf.json.JSONObject;

public class MainBoardReply {

	// pk
	private int seq;

	private int main_seq;
	private String title;
	private String name;
	private Date date;
	private int count;
	private String content;

	private String delete_flag = "N";

	public void setSeq(int seq) {
		this.seq = seq;
	}

	public int getSeq() {
		return this.seq;
	}

	public void setMain_seq(int main_seq) {
		this.main_seq = main_seq;
	}

	public int getMain_seq() {
		return this.main_seq;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getTitle() {
		return this.title;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return this.name;
	}

	public void setDate(Date date) {
		this.date = date;
	}

	public Date getDate() {
		return this.date;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public int getCount() {
		return this.count;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public String getContent() {
		return this.content;
	}

	public String getDelete_flag() {
		return delete_flag;
	}

	public void setDelete_flag(String delete_flag) {
		this.delete_flag = delete_flag;
	}

	public JSONObject getJSONObject() {
		JSONObject jobj = new JSONObject();
		jobj.put("seq", this.seq);
		jobj.put("main_seq", this.main_seq);
		jobj.put("title", this.title);
		jobj.put("name", this.name);
		jobj.put("date", DateUtils.datetoIsoDate(this.date));
		jobj.put("count", this.count);
		jobj.put("content", this.content);
		return jobj;
	}
}

MainBoardReplyMapper 인터페이스 생성

package com.iot.db.mapper;

import java.util.List;
import java.util.Map;

import com.iot.db.domain.MainBoardReply;

public interface MainBoardReplyMapper {

	public MainBoardReply selectMainBoardReply(Map<String, Object> params);

	public void insertMainBoardReply(MainBoardReply mainBoardReply);

	public void updateMainBoardReply(MainBoardReply mainBoardReply);

	public void deleteMainBoardReply(Map<String, Object> params);

	public int getCount();

	public int getCountFormData(Map<String, Object> params);

	public List<MainBoardReply> listMainBoardReply(Map<String, Object> map);

}

MainBoardReplyMapper.xml 생성

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.iot.db.mapper.MainBoardReplyMapper">

	<!-- selectMainBoardReply -->
	<select id="selectMainBoardReply" parameterType="map" resultType="com.iot.db.domain.MainBoardReply">
	  select seq
	         ,main_seq
	         ,title
	         ,name
	         ,date
	         ,count
	         ,content
	    from main_board_reply
	   where seq = #{seq}
	</select>
	
	<!-- updateMainBoardReply -->
	<update id="updateMainBoardReply" parameterType="com.iot.db.domain.MainBoardReply" statementType="PREPARED">
	    update main_board_reply
	      <trim prefix="SET" suffixOverrides=",">
	        <if test="main_seq != null">main_seq = #{main_seq, jdbcType=INTEGER} ,</if>
	        <if test="title != null">title = #{title, jdbcType=VARCHAR} ,</if>
	        <if test="name != null">name = #{name, jdbcType=VARCHAR} ,</if>
	        <if test="date != null">date = #{date, jdbcType=DATE} ,</if>
	        <if test="count != null">count = #{count, jdbcType=INTEGER} ,</if>
	        <if test="content != null">content = #{content, jdbcType=VARCHAR} ,</if>
	      </trim>
	   where seq = #{seq}
	</update>
	
	<!-- insertMainBoardReply -->
	<insert id="insertMainBoardReply" parameterType="com.iot.db.domain.MainBoardReply" statementType="PREPARED">
	    insert into main_board_reply(
	      <trim suffixOverrides=",">
	        <if test="main_seq != null">main_seq ,</if>
	        <if test="title != null">title ,</if>
	        <if test="name != null">name ,</if>
	        <if test="date != null">date ,</if>
	        <if test="count != null">count ,</if>
	        <if test="content != null">content ,</if>
	      </trim>
	      ) values	(
	      <trim suffixOverrides=",">
	        <if test="main_seq != null">#{main_seq, jdbcType=INTEGER} ,</if>
	        <if test="title != null">#{title, jdbcType=VARCHAR} ,</if>
	        <if test="name != null">#{name, jdbcType=VARCHAR} ,</if>
	        <if test="date != null">#{date, jdbcType=DATE} ,</if>
	        <if test="count != null">#{count, jdbcType=INTEGER} ,</if>
	        <if test="content != null">#{content, jdbcType=VARCHAR} ,</if>
	      </trim>
	      )
	</insert>
	
	<!-- deleteMainBoardReply -->
	<delete id="deleteMainBoardReply" parameterType="map" statementType="PREPARED">
	    delete from main_board_reply
	   where seq = #{seq}
	</delete>
	
	<!-- getCount -->
	<select id="getCount" resultType="int">
	  select count(*)
	    from main_board_reply
	</select>
	
	<!-- getCountFormData -->
	<select id="getCountFormData" parameterType="map" resultType="int">
	  select count(*)
	    from main_board_reply
	    <trim prefix="WHERE" prefixOverrides="AND |OR ">
	      <if test="searchstr != null">and title like '%${searchstr}%'</if>
	    </trim>
	</select>
	
	<!-- listMainBoardReply -->
	<select id="listMainBoardReply" parameterType="map" resultType="com.iot.db.domain.MainBoardReply">
	  select * 
	    from main_board_reply
	   where main_seq = #{main_seq}
	</select>

</mapper>

MainBoardReplyService 클래스 생성

package com.iot.db.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.iot.db.domain.MainBoardReply;
import com.iot.db.mapper.MainBoardReplyMapper;

@Service
public class MainBoardReplyService {

	public final static int pagerowcnt = 25;

	@Autowired
	private MainBoardReplyMapper mainBoardReplyMapper;

	public MainBoardReply selectMainBoardReply(int seq) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("seq", seq);
		return mainBoardReplyMapper.selectMainBoardReply(params);
	}

	public void insertMainBoardReply(MainBoardReply mainBoardReply) {
		mainBoardReplyMapper.insertMainBoardReply(mainBoardReply);
	}

	public void updateMainBoardReply(MainBoardReply mainBoardReply) {
		mainBoardReplyMapper.updateMainBoardReply(mainBoardReply);
	}

	public void deleteMainBoardReply(int seq) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("seq", seq);
		mainBoardReplyMapper.deleteMainBoardReply(params);
	}

	public void deleteMainBoardReply(Map<String, Object> params) {
		mainBoardReplyMapper.deleteMainBoardReply(params);
	}

	public int getCount() {
		return mainBoardReplyMapper.getCount();
	}

	public List<MainBoardReply> listMainBoardReply(int main_seq) throws Exception {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("main_seq", main_seq);
		return mainBoardReplyMapper.listMainBoardReply(params);
	}

}

댓글 입력 Form (jsp에 반영)

<form action="<c:url value="/insertReplyPage.iot"/>" method="post">
	<input type="hidden" name="main_seq" value="${seq}"/>
	<textArea name ="comment" cols="60" rows="20"></textArea>
	<input type="submit" value="답변 입력">
	<input type="button" value="취 소">
</form>

댓글 입력 처리 (컨트롤러에 반영)

	@Autowired
	MainBoardReplyService replyService;

	@RequestMapping(value = "/insertReplyPage.iot", method = RequestMethod.POST)
	public String insertReplyPage(
			@RequestParam("main_seq") int main_seq,
			@RequestParam("comment") String comment,
			ModelMap modelMap) throws Exception 
	{
		
		System.out.println("main_seq = " + main_seq + "/" + comment);
		
		MainBoardReply reply = new MainBoardReply();
		reply.setMain_seq(main_seq);
		reply.setContent(comment);
		
		replyService.insertMainBoardReply(reply);
		
		return "redirect:/moveToMainBoard.iot";
	}

게시판 도메인에 댓글 목록 추가

	private List<MainBoardReply> replyList;
	
	public List<MainBoardReply> getReplyList() {
		return replyList;
	}
	public void setReplyList(List<MainBoardReply> replyList) {
		this.replyList = replyList;
	}

게시판 리스트 (컨트롤러에 반영)

	@RequestMapping(value = "/moveToMainBoard.iot", method = RequestMethod.GET)
	public String moveToMainBoard(ModelMap modelMap) throws Exception {
		
		// 게시판 내용 조회
		List<main_boardDto> main_boardDtoList = service.selectMainBoardList();
		
		// 댓글 조회
		for (main_boardDto board: main_boardDtoList) {
			List<MainBoardReply> replyList = replyService.listMainBoardReply(board.getSeq());
			board.setReplyList(replyList);
		}
		
		System.out.println("main_baordDto : " +main_boardDtoList);
		modelMap.addAttribute("main_boardDto",main_boardDtoList);
		return "/main_board";
	}

게시판 리스트 (jsp에 반영)

  <c:forEach items="${main_boardDto}" var="data" varStatus="loop">
  	<tr>
  		<td><input type="checkbox" name="delete_seqs" value="${data.seq}"/></td>
  		<td>${data.seq}</td>
  		<td class="underline" onclick="javascript:readContent(${data.seq});">${data.title}</td>
  		<td onclick="javascript:modifyExplanation_content(${data.seq});">${data.name}</td>
  		<td>${data.date}</td>
  		<td>${data.count}</td>
    </tr>
    <c:forEach items="${data.replyList}" var="reply" varStatus="loop">
  	  <tr>
  		<td><input type="checkbox" name="delete_seqs" value="${reply.seq}"/></td>
  		<td>${reply.seq}</td>
  		<td>  -> ${reply.content}</td>
  		<td>${reply.name}</td>
  		<td>${reply.date}</td>
  		<td>${reply.count}</td>
      </tr>
    </c:forEach>
  </c:forEach>
728x90
728x90

출처 : IT 조각 모음: [java] spring3 + tiles3 설정 하기

iot-servlet.xml 내용추가(WebContent\WEB-INF\iot-servlet.xmll)

	<!-- 타일즈 설정 : 시작 -->
	<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
		<property name="viewClass" value="org.springframework.web.servlet.view.tiles3.TilesView" />
		<property name="order" value="1"/>
	</bean>
	<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
		<property name="definitions">
 			<list>
				<value>/WEB-INF/tiles/tiles-layout.xml</value>
			</list>
		</property>
 	</bean>
 	<!-- 타일즈 설정 : 종료 -->

타일즈 환경설정 파일 생성(WebContent\WEB-INF\tiles\tiles-layout.xmll)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC 
	"-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN" 
	"http://tiles.apache.org/dtds/tiles-config_3_0.dtd">	

<tiles-definitions>
	
	<definition name="/*.blank" template="/WEB-INF/tiles/blankLayout.jsp">
		<put-attribute name="content"	value="/WEB-INF/jsp/{1}.jsp"/>
	</definition>
	
	<definition name="/*" template="/WEB-INF/tiles/web_layout.jsp">
		<put-attribute name="header" value="/WEB-INF/tiles/web_header.jsp" />
		<put-attribute name="main" value="/WEB-INF/jsp/{1}.jsp" />
		<put-attribute name="footer" value="/WEB-INF/tiles/web_footer.jsp" />	
	</definition>
	
</tiles-definitions>

레이아웃(web_layout.jsp) 파일 생성(WebContent\WEB-INF\tiles\web_layout.jsp)

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0 minimal-ui"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black">
</head>

<body>

<div id="wrap">
	<!-- head -->
	<div id="header"><tiles:insertAttribute name="header" /></div>
	
	<!-- content -->
	<div id="body">
		<div id="container"><tiles:insertAttribute name="main" /></div>
	</div>

	<!-- footer -->
	<div id="footer"><tiles:insertAttribute name="footer" /></div>
</div>
	
</body>
</html>

상당 페이지(web_header.jsp) 파일 생성(WebContent\WEB-INF\tiles\web_header.jsp)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>

<div>
로그인사용자 : <sec:authentication property="principal.username" />
</div>

<div>
	<a href="<c:url value="/j_spring_security_logout"/>">로그아웃</a> 
	<a href="<c:url value="/user_add_ajax.iot"/>">회원 가입</a>
</div>

하단 페이지(web_footer.jsp) 파일 생성(WebContent\WEB-INF\tiles\web_footer.jsp)

<%@ page contentType="text/html;charset=utf-8"%>

<div>
회사이름 : 파란크리스마스
</div>

실행결과

footer 하단영역에 고정시키기 (WebContent\WEB-INF\tiles\web_layout.jsp 내용추가)

출처 : footer 하단영역에 고정시키기 | 신기한 웹 세상

<style>
html, body { margin:0; padding:0; height:100%; }
#wrap {
    height:100%;
}
#header {
    position:relative;
    width:100%;
    height:45px;
    background-color:#eaeaea;
}
#body {
    margin:-45px 0 -50px;
    width:100%;
    min-height:100%;
}
#body #container {
    padding:45px 0 50px;
}
 
#footer {
    width:100%;
    height:50px;
    background-color:#eaeaea;
}
</style>

스타일 적용 실행결과

상하단 페이지가 필요없는 경우 처리(WebContent\WEB-INF\tiles\blankLayout.jsp 생성)

<jsp:directive.page import="org.springframework.web.context.request.RequestAttributes"/>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles"%>
<tiles:insertAttribute name="content"/>

로그인 페이지 blankLayout 사용(src\com\iot\controller\LoginController.java 내용수정)

return "/login"; 에서 return "/login.blank"; 로 수정

	@RequestMapping(value = "/login.iot", method = RequestMethod.GET)
	public String login(ModelMap modelMap) throws Exception {
		return "/login.blank";
	}

blankLayout 적용 전후

  

728x90
728x90

Spring Security

출처 : 사랑이 고픈 프로그래머.. - 흔히 보게되는 절대 써먹을 수 없는 Spring Security의 초간단 셋팅
jjeong :: Spring Security login/logout 관련 글

web.xml 내용추가(WebContent\WEB-INF\web.xml)

	<!-- 스프링 스큐리티 관련 설정 / 시작 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/iot-datasource.xml
			/WEB-INF/iot-mybatis.xml
			/WEB-INF/iot-security.xml
		</param-value>
	</context-param>
	
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<!-- 스프링 스큐리티 관련 설정 / 끝 -->

iot-security.xml 파일 생성(WebContent\WEB-INF\iot-security.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:security="http://www.springframework.org/schema/security"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
           http://www.springframework.org/schema/security
           http://www.springframework.org/schema/security/spring-security-3.2.xsd">

	<!-- 확장자를 이용해 패턴을 걸때는 /**/*.해당 확장자 로 할 것(Ant Pattern 규칙) -->
	<security:http pattern="/**/*.js" security="none"/>
	<security:http pattern="/**/*.css" security="none"/>
	<security:http pattern="/images/*" security="none"/>
	
	<!--
	<security:http pattern="/user_add_ajax.iot" security="none" //>
	<security:http pattern="/login.iot" security="none" />
	<security:http pattern="/loginfailed.iot" security="none" />
	<security:http pattern="/logout.iot" security="none" />
	-->
	
	<security:http auto-config="true">
		<security:intercept-url pattern="/json.iot" access="ROLE_ANONYMOUS,ROLE_USER" />
		<security:intercept-url pattern="/**/*.iot" access="ROLE_USER"/>
		
		<!-- 
		<security:form-login login-page="/login.iot" default-target-url="/hello_world.iot" authentication-failure-url="/loginfailed.iot" />
		<security:logout logout-success-url="/login.iot" />
		-->
	</security:http>

	<security:authentication-manager>
		<security:authentication-provider>

			<security:jdbc-user-service
				data-source-ref="dataSource"
				users-by-username-query="select user_id username, password password, 1 as enabled from user_info where user_id = ?"
				authorities-by-username-query="select name username, 'ROLE_USER' authority from user_info where user_id = ?" />

		</security:authentication-provider>
	</security:authentication-manager>

</beans>

로그인 페이지 만들기

package com.iot.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class LoginController {

	@RequestMapping(value = "/login.iot", method = RequestMethod.GET)
	public String login(ModelMap modelMap) throws Exception {
		return "/login";
	}
}

로그인페이지 추가 (WebContent\WEB-INF\jsp\login.jsp)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login Page</title>
<style>
.errorblock {
	color: #ff0000;
	background-color: #ffEEEE;
	border: 3px solid #ff0000;
	padding: 8px;
	margin: 16px;
}
</style>
</head>
<body onload='document.f.j_username.focus();'>

 <div id="background_login">
	<h3>IOT 로그인 페이지</h3>
 
	<c:if test="${not empty error}">
		<div class="errorblock">
			Your login attempt was not successful, try again.<br /> Caused :
			${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
		</div>
	</c:if>

	<form name='f' action="<c:url value='j_spring_security_check' />" method='POST'>
		<table>
			<tr>
				<td>사용자ID : </td>
				<td><input type='text' name='j_username' value=''>
				</td>
			</tr>
			<tr>
				<td>PassWord : </td>
				<td><input type='password' name='j_password' />
				</td>
			</tr>
			<tr>
				<td><input name="submit" type="submit" value="로그인" />
				<td><input name="reset" type="reset" />
				</td>
			</tr>
		</table>
	</form>
</div>

<a href="<c:url value='/user_add_ajax.iot' />">사용자추가</a>

</body>
</html>

시큐리티 제외 주소 설정

iot-security.xml 파일 내용 추가(WebContent\WEB-INF\iot-security.xml)

로그인 관련 주소는 시큐리티 설정에서 제외 시킨다.

	<security:http pattern="/user_add_ajax.iot" security="none" />
	<security:http pattern="/login.iot" security="none" />
	<security:http pattern="/loginfailed.iot" security="none" />
	<security:http pattern="/logout.iot" security="none" />

로그인 페이지 설정

iot-security.xml 파일 내용 추가(WebContent\WEB-INF\iot-security.xml)

		<security:form-login login-page="/login.iot" 
			default-target-url="/hello_world.iot" 
			authentication-failure-url="/loginfailed.iot" />
		<security:logout logout-success-url="/logout.iot" />

로그아웃

웹페이지 주소에 /j_spring_security_logout 이동하면 로그아웃

로그인 아웃 페이지 만들기(src\com\iot\controller\LoginController.java)

	@RequestMapping(value = "/logout.iot", method = RequestMethod.GET)
	public String logout(ModelMap modelMap) throws Exception {
		return "/logout";
	}

로그인아웃 페이지 추가 (WebContent\WEB-INF\jsp\logout.jsp)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login Page</title>
</head>
<body>
	<h3>로그아웃</h3>	
	<a href="<c:url value="j_spring_security_logout" />" >로그아웃</a>
</body>
</html>

컨트롤러에서 로그인 아이디 얻기

	Authentication auth = SecurityContextHolder.getContext().getAuthentication();
	String user_id = auth.getName();


728x90

+ Recent posts