@RequestMapping("/reply_view")
public String reply_view(HttpServletRequest request, Model model) {
System.out.println("reply_view start...");
model.addAttribute("request", request);
command = new BReplyViewCommand();
command.execute(model);
return "reply_view";
}
@RequestMapping(value = "/reply", method = RequestMethod.POST)
public String reply(HttpServletRequest request, Model model) {
System.out.println("reply()");
model.addAttribute("request", request);
command = new BReplyCommand();
command.execute(model);
return "redirect:list";
}
package com.oracle.oMVCBoard.command;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.ui.Model;
import com.oracle.oMVCBoard.dao.BDao;
public class BReplyCommand implements BCommand {
@Override
public void execute(Model model) {
Map<String, Object> map = model.asMap();
HttpServletRequest request = (HttpServletRequest) map.get("request");
String bId = request.getParameter("bId");
String bName = request.getParameter("bName");
String bTitle = request.getParameter("bTitle");
String bContent = request.getParameter("bContent");
// int bGroup = Integer.parseInt(request.getParameter("bGroup"));
// int bStep = Integer.parseInt(request.getParameter("bStep"));
// int bIndent = Integer.parseInt(request.getParameter("bIndent"));
String bGroup = request.getParameter("bGroup");
String bStep = request.getParameter("bStep");
String bIndent = request.getParameter("bIndent");
BDao dao = new BDao();
dao.reply(bId, bName, bTitle, bContent, bGroup, bStep, bIndent);
}
}
public void reply(String bId, String bName, String bTitle, String bContent,
String bGroup, String bStep, String bIndent) {
// TODO Auto-generated method stub
// 홍해 기적
replyShape(bGroup, bStep);
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = dataSource.getConnection();
String query = "insert into mvc_board (bId, bName, bTitle, bContent, "
+ " bGroup, bStep, bIndent)"
+ " values (mvc_board_seq.nextval, ?, ?, ?, ?, ?, ?)";
preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, bName);
preparedStatement.setString(2, bTitle);
preparedStatement.setString(3, bContent);
preparedStatement.setInt(4, Integer.parseInt(bGroup));
preparedStatement.setInt(5, Integer.parseInt(bStep) + 1);
preparedStatement.setInt(6, Integer.parseInt(bIndent) + 1);
int rn = preparedStatement.executeUpdate();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
try {
if(preparedStatement != null) preparedStatement.close();
if(connection != null) connection.close();
} catch (Exception e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
}
private void replyShape( String strGroup, String strStep) {
// TODO Auto-generated method stub
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = dataSource.getConnection();
String query = "update mvc_board set bStep = bStep + 1 "
+ " where bGroup = ? and bStep > ?";
preparedStatement = connection.prepareStatement(query);
preparedStatement.setInt(1, Integer.parseInt(strGroup));
preparedStatement.setInt(2, Integer.parseInt(strStep));
int rn = preparedStatement.executeUpdate();
} catch (Exception e) {
// TODO: handle exceptionu
e.printStackTrace();
} finally {
try {
if(preparedStatement != null) preparedStatement.close();
if(connection != null) connection.close();
} catch (Exception e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
}
한글처리, security-context.xml, securityChain 추가
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/root-context.xml
/WEB-INF/spring/appServlet/security-context.xml
</param-value>
</context-param>
<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>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 한글처리 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
security library 추가 + 버전 4.1.3 올리기
bean + security 추가
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<security:http auto-config="true">
<security:intercept-url pattern="/login.html" access="ROLE_USER"/>
<security:intercept-url pattern="/welcome.html" access="ROLE_ADMIN"/>
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="user" password="123" authorities="ROLE_USER"/>
<security:user name="admin" password="123" authorities="ROLE_ADMIN"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
@RequestMapping("/login.html")
public String login(Model model) {
logger.info("Welcome login.html");
return "security/login";
}
@RequestMapping("/welcome.html")
public String welcome(Model model) {
logger.info("Welcome welcome.html");
return "security/welcome";
}
📂 security
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Login 성공</h1>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Welcome 성공</h1>
</body>
</html>
🙆♀️user
⚙admin
❌로그인 후 페이지 이동을 했을 때?
로그인이 되어있는 상태라 이동불가
참고
web.xml, pom.xml 위와 동일
📂 WEB-INF - spring - appServlet
admin은 유저페이지/관리자페이지 접근 권한 줌
<security:user name="admin" password="123" authorities="ROLE_ADMIN, ROLE_USER"/>```
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<security:http auto-config="true">
<security:form-login login-page="/loginForm.html" authentication-failure-url="/loginForm.html?error"/>
<security:intercept-url pattern="/login.html" access="ROLE_USER"/>
<security:intercept-url pattern="/welcome.html" access="ROLE_ADMIN"/>
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="user" password="123" authorities="ROLE_USER"/>
<security:user name="admin" password="123" authorities="ROLE_ADMIN, ROLE_USER"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
package com.oracle.security2;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
@RequestMapping("/login.html")
public String login(Model model) {
System.out.println("HomeController login.html Start...");
return "security/login";
}
@RequestMapping("/welcome.html")
public String welcome(Model model) {
System.out.println("HomeController welcome.html Start...");
return "security/welcome";
}
@RequestMapping("/loginForm.html")
public String loginForm(Model model) {
System.out.println("HomeController loginForm.html Start...");
return "security/loginForm";
}
}
📂 security
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Welcome 성공</h1>
</body>
</html>
내부적으로 session을 사용하며 j_spring_security_logout를 통해 session을 빠져나간다.
<%@ 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>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Login 성공</h1>
<c:if test="${not empty pageContext.request.userPrincipal}">
${pageContext.request.userPrincipal}
<p> is Log-In</p>
</c:if>
<c:if test="${empty pageContext.request.userPrincipal}">
<p> is Log-Out</p>
</c:if>
USER ID : ${pageContext.request.userPrincipal.name} </br>
<a href="${pageContext.request.contextPath}/j_spring_security_logout">Log Out</a></br>
</body>
</html>
j_spring_security_check -> spring security 예약어, spring 내부에서 해결
j_username, j_password 약속이자 강제
<%@ 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>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>내가 만드는 Security Login Form</h1>
<c:url value="j_spring_security_check" var="loginUrl"/>
<h5>loginUrl : ${loginUrl}</h5>
<form action="${loginUrl}" method="post">
<c:if test="${param.error != null}">
<p>
LogIn Error!<br/>
<c:if test="${SPRING_SECURITY_LAST_EXCEPTION != NULL}">
message : <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message }"></c:out>
</c:if>
</p>
</c:if>
ID : <input type="text" name="j_username"><br/>
PW : <input type="text" name="j_password"><br/>
<input type="submit" value="LOGIN"><br/>
</form>
</body>
</html>
💻로그인페이지
❌잘못 입력했을 시
⭕정상입력 + /login.html -> 로그아웃도 가능
⛔유저가 관리자페이지로 이동하면?
👉로그아웃하고 url를 누르면 다시 로그인 페이지로 들어감
⚙관리자로 로그인 후 유저페이지를 들어가면?
xml을 사용할 때마다 사용자의 아이디와 비번을 입력을 해줘야하는 걸까?
-> spring-boot에서 DB에서 받아와서 할 예정이다 + 암호화도 배울 예정
참고페이지
요즘엔 legacy를 많이 사용하지 않기 때문에 maven보단 gradle를 더 많이 사용
⭐add dependencies 에서 spring web+thymeleaf 추가
pom.xml == build.gradle
- group : 회사이름
- sourceCompatibility : java 버전
- dependencies : 프로젝트에서 사용할 디펜던시 묘듈을 정의 ( 요즘에는 프로젝트 Test가 중요해졌다
- 오른쪽 마우스 -> gradle -> Refresh Gradle Project하면 실행됨
plugins {
id 'org.springframework.boot' version '2.7.5'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'java'
}
group = 'com.oracle'
version = 'version1.0'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
application.properties == web.xml
📂 src/main/resources
server.port=8381
package com.oracle.oBootHello.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
private static final Logger logger = LoggerFactory.getLogger(HelloController.class);
@RequestMapping("hello")
public String hello(Model model) {
// prefix -> templates
// suffix -> .html
logger.info("start...");
model.addAttribute("parameter", "boot start...");
return "hello";
}
}
📂 src/main/resource - templates
templates -> view
<html xml:th="http://www.thymeleaf.org"> -> 타임리프 가져오기
<p th:text="안녕+${parameter}"> -> 텍스트 입력
<!DOCTYPE html>
<html xml:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>hello.html</h1>
<p th:text="안녕+${parameter}">
</body>
</html>
📂 src/main/resource - static
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>나 Index야</h1>
</body>
</html>
🤔만약 kkk.html을 만든다면?
❌index가 아니기 때문에 오류남❌
📂 src/main/resource - static
- kkk.html
📂 src/main/resource - static
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>나 Index야</h1>
<a href="/hello">Hello</a>
</body>
</html>
앵커로 hello연결
🔎 리런칭
🔹 Spring boot
- 내장 탐캣을 가지고 있다
- @ResponseBody : view Resolver를 타지 않고 HttpMessageConverter를 탄다.
- HttpMessageConverter : String타입을 받으면 StringConverter를 타고 객체타입을 받으면 JsonConverter를 탄다.
클라이언트에서 서버로 통신하는 메시지를 요청(request) 메시지라고 하며, 서버에서 클라이언트로 통신하는 메시지를 응답(response) 메시지라고한다.
웹에서 화면전환 없이 이루어지는 동작들을 대부분 비동기 통신으로 이루어진다.
비동기 통신을 하기 위해서는 클라이언트에서 서버로 요청 메시지를 보낼 때, 본문에 데이터를 담아서 보내야 하고, 서버에서 클라이언트로 응답을 보낼때에도 본문에 데이터를 담아서 보내야한다.
여기서 본문이랑 Body 이다.
즉 요청본문 requestBody. 응답본문 responseBody을 담아서 보내야 한다.
이때 본문에 담기는 데이터 형식은 여러가지 형태가 있겠지만 가장 대표적으로 사용되는 것이 JSON이다. 즉 비동기식 클라이언트 - 서버 통신을 위해 JSON형식의 데이터를 주고받는 것이다.
package com.oracle.oBootHello.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
private static final Logger logger = LoggerFactory.getLogger(HelloController.class);
@RequestMapping("hello")
public String hello(Model model) {
// prefix -> templates
// suffix -> .html
logger.info("start...");
model.addAttribute("parameter", "boot start...");
return "hello";
}
@ResponseBody
@GetMapping("ajaxString")
public String ajaxString(@RequestParam("ajaxName") String aName) {
System.out.println("HelloController ajaxString aName->"+aName);
return aName;
}
}
package com.oracle.oBootHello.domain;
public class Emp {
private String empno;
private String ename;
public String getEmpno() {
return empno;
}
public void setEmpno(String empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
}
객체로 들어오면 Json Converter가 처리를 한다.
@ResponseBody
@GetMapping("ajaxEmp")
public Emp ajaxEmp(@RequestParam("empno") String empno, @RequestParam("ename") String ename) {
System.out.println("HelloController ajaxEmp empno->"+empno);
logger.info("ename -> {}", ename);
Emp emp = new Emp();
emp.setEmpno(empno);
emp.setEname(ename);
return emp;
}
JSON 형식의 requestBody