CRUD — это четыре необходимые функции приложения хранилища

  • Создайте
  • читать
  • Обновить
  • Удалить

Сегодня давайте посмотрим, как создать простой веб-сайт блога с помощью Spring MVC.

  1. создать устаревший проект
  2. Изменить версию Spring в pom.xml
  3. Добавить тест Spring, Spring JDBC, Spring tx
  4. Изменить версию Junit
  5. Изменить версию сервлета
  6. Добавить HiakriCp, MyBatis, Mybatis-spring, Log4jdbc
  7. Добавьте драйвер JDBC в проект.
  8. Настройка Ломбок и т. д.

Добавить зависимость из репозитория Maven в pom.xml



«Репозиторий Maven: поиск/обзор/исследование
no.priv.bang.authservice “ authservice.definitions “ 1.11.13 Apachemvnrepository.com”



Плюсы и минусы Хикари.

  • Быстрый с небольшим количеством пользователей (до 16000)
  • Может быть медленным с большим количеством пользователей
<!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.5</version>
</dependency>

Log4jdbc

  • Распечатать лог.
  • Полезно для разработчиков.

Вот видео с экрана

  • создать проект
  • добавить зависимости из репозитория maven

добавить зависимости из репозитория maven

spring tx: весенняя транзакция 5.2.8

Пул подключения к БД

-hikaricp

мибатис 3.5.5

мибатис весна 2.0.5

Ломбок 1.18.12

  • Бин
  • Аннотация — автоматически генерировать геттер и сеттер.
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>

Log4Jdbc Log4j2 JDBC 4 1

<dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
<version>1.16</version>
</dependency>
  • изменить путь к серверу
  • установить языковой фильтр (корейский)

→ Скопируйте и вставьте соответствующий фильтр в файл XML

Оракул

1. создать учетную запись

2. Создайте таблицу и вставьте строку

создать последовательность seq_board;

create sequence seq_board;
create table board(
bno number primary key, 
title varchar2(100) not null, 
content varchar2(2000)not null,
writer varchar2(50) not null, 
regdate date default sysdate, 
updatedate date default sysdate);
insert into board(bno,title, content, writer)values (seq_board.nextval,
'테스트 제목' ,'테스트내용' ,'user01');
select * from baord;

выберите * с доски; вот видео процесса.

Для подключения к базе данных

подключить пул

<!-- Root Context: defines shared resources visible to all other web components -->
<!-- resource적는거임 -->
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<!-- <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:XE"/> -->
<property name="driverClassName"
value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
<property name="jdbcUrl"
value="jdbc:log4jdbc:oracle:thin:@localhost:1521:XE"></property>
<property name="username" value="spring" />
<property name="password" value="1234" />
</bean>

Фабрика сеансов SQL

<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- datasource로  -->
<property name="dataSource" ref="dataSource" />
</bean>

создайте пакет для создания картографа.

Сопоставьте путь с BoardMapper.java

→ Сервис → Контроллер → Возврат результата

контроллер.java

package org.knr.boardex001.controller;
import org.knr.boardex001.domain.BoardVO;
import org.knr.boardex001.service.BoardService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import lombok.AllArgsConstructor;
import lombok.extern.java.Log;
import oracle.net.ano.Service;
@Controller
@Log
@RequestMapping("/board")
@AllArgsConstructor
public class BoardController {
 
 private BoardService service;
 @GetMapping("/list")
 public void list(Model model) {
  log.info("list..........!");
  model.addAttribute("list",service.getList());
 }
 
 @GetMapping("/register")
 public void register() {
 }
 
 @PostMapping("/register")
 public String registerPro(BoardVO board,RedirectAttributes rttr) {
  log.info("registerPro");
  service.register(board);
  rttr.addFlashAttribute("result", board.getBno());
  return "redirect:list";
 }
 
 @GetMapping("/get")
 public void get(Long bno,Model model) {
  log.info("get");
  model.addAttribute("board", service.get(bno));
 }
 @PostMapping("/update")
 public String update(BoardVO board) {
  log.info("update");
  if(service.modify(board)) {
   return "redirect:list";
  }else {
   return "redirect:get";
  }
  
 }
 @GetMapping("/delete")
 public String delete(Long bno) {
  log.info("delete");
  if(service.remove(bno)) {
   return "redirect:list";
  }else {
   return "redirect:get";
  }
 }
 
 
 
}

Добавить objdbc6.jar

  1. проект → путь сборки → настроить путь сборки → добавить внешний Jar
  2. Построить путь

проект → свойства→ сборка развертывания→ добавить

→записи путей сборки java

УСТАНОВИТЬ контекст данных

  • Запись ресурса
  • Настройка отношения к базе данных

Пакет домена

  • то же самое с содержимым базы данных оракула

"@Данные"

package org.knr.boardex001.domain;
import java.util.Date;
import lombok.Data;
@Data
public class BoardVO {
private Long bno; 
private String title; 
private String content; 
private Date regdate;
private Date updatedate;
}

Сопоставитель

  • сделать как интерфейс

package org.knr.boardex001.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Select;
import org.knr.boardex001.domain.BoardVO;
//원래 결과arraylist에 넣던거를 이렇게 간단하게 할수있음 
public interface BoardMapper {
 @Select("select * from board where bno>0")
 public List<BoardVO> getList();

дайте знать расположение Mybatis‹путь BoardMapper в моем примере›

в корневом контексте.xml

<mybatis-spring:scan base-package="org.knr.boardex001.mapper"/>

Тестовое подключение к базе данных с тестовым кодом

если это не работает, попробуйте обновление maven

package org.knr.boardex001;
import java.sql.Connection;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.knr.boardex001.domain.BoardVO;
import org.knr.boardex001.mapper.BoardMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import lombok.Setter;
import lombok.extern.log4j.Log4j;
//junit가지고 테스트 할게요 
@RunWith(SpringJUnit4ClassRunner.class)
//안에 db설정한 파일 설정한거
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
//로그 찍는거 
//함수를 쓰려면 객체를 만들어야 되는데
// 객체를 가져와야 하는데 객체를 못 만들기 때문에
@Log4j
public class BoardMapperTest {
@Setter(onMethod_ = @Autowired)
 private BoardMapper mapper;
@Setter(onMethod_ = @Autowired)
 private DataSource dataSource;
@Test
 public void testConnection() {
try (Connection conn = dataSource.getConnection()) {
log.info(conn);
} catch (Exception e) {
   e.printStackTrace();
}
 }
// mapper에 getlist의 결과를 얻어와서 각각의 것을 board에 넣어서 log.info를 출력함
 @Test
 public void testGList() {
mapper.getList().forEach(board -> log.info(board));
 }
@Test
 public void testInsert() {
BoardVO board = new BoardVO();
  board.setTitle("새글 제목");
  board.setContent("새글 내용");
  board.setWriter("newUser");
  mapper.insertSelectKey(board);
  log.info(board);
}
@Test
 public void testRead() {
  // L을 붙이는 이유는 Long이라서
  BoardVO board = mapper.read(1L);
  log.info(board);
 }
@Test
 public void testDelete() {
  int n= mapper.delete(2l);
  if(n==1) {
   log.info("삭제성공");
  }
 }
 
 @Test
 public void testUpdate() {
  
  BoardVO board = new BoardVO(); 
  board.setBno(1L); 
  board.setTitle("수정제목");
  board.setContent("수정내용");
  board.setWriter("user01");
  int n =mapper.update(board);
  if(n==1) {
   log.info("수정성공");
  }
 }
}

Добавить Мибатиса

получить источник данных из нижней части файла корневого контекста

<?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:context="http://www.springframework.org/schema/context"
 xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
 xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
  http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
 <!-- resource적는거임 -->
 <bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
  <!-- 데이터베이스,url, pw뭔지 -->
  <property name="driverClassName"
   value="oracle.jdbc.driver.OracleDriver" />
  <property name="jdbcUrl"
   value="jdbc:oracle:thin:@localhost:1521:XE"></property>
  <property name="username" value="spring" />
  <property name="password" value="1234" />
</bean>
 <!-- 실제로 resource얻을때 datasource로 얻음 이 안에 데이터 설정해 놓은 hikariConfig를 넣는다. -->
 <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
  <constructor-arg ref="hikariConfig" />
</bean>
 <!-- 하나 접속이 세션 그걸 생성하는 factorybean -->
 <!-- mybatis는 sql로 이루어져 있고 , 접속하는bean을 만드는 factory -->
 <!-- 원래는 field로 datasource를 들고 있음 -->
 <!-- jsp로 할때는 없어도 되는데 지금은 my batis를 사용하기 때문에 필요함 -->
 <bean id="sqlSessionFactory"
  class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- datasource로  -->
  <property name="dataSource" ref="dataSource" />
</bean>
<!--  mybatis가 어디 있는지  -->
 <mybatis-spring:scan base-package="org.knr.boardex001.mapper"/>
<!--  스캔하는 default package  -->
 <context:component-scan base-package="org.knr.boardex001"/>
 
</beans>

Коннекпул

  • Сохраните использованный и принесите его из бассейна.
  • Добавьте драйвер JDBC в проект.

Разрешить Eclipse использовать Lombok.

Эта часть тестируется непосредственно прямым впрыском.

@Setter(onMethod_=@Autowired)
 private DataSource dataSource;

Внедрить этот компонент

<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
  <constructor-arg ref="hikariConfig" />
</bean>

Контекст сервлета

  • Включить бины, управляющие веб-настройкой
  • найти местоположение контроллера
  • Логический вид -> физический вид

Корневой контекст

Настройки отличные от сети.

Сделать маппер с MyBatis



<?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">
우리가 만들 mybatis의 namespace위치 
<mapper namespace="org.mybatis.example.BlogMapper">
  <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
  </select>
</mapper>
<?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="org.knr.boardex001.mapper.BoardMapper">
<select id="getList"
  resultType="org.knr.boardex001.domain.BoardVo">
<!--   where절을 넣지 않으면 index사용 안함  -->
  select * from board
 </select>
</mapper>
<?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="org.knr.boardex001.mapper.BoardMapper">
<select id="getList"
  resultType="org.knr.boardex001.domain.BoardVo">
  <!-- where절을 넣지 않으면 index사용 안함 -->
  select * from board
 </select>
<insert id="insert">
  insert into board(bno, title, content, writer)
  values
  (seq_board.nextval, #{title},#{content},#{writer})
 </insert>
<insert id="insertSelectKey">
  <selectKey keyProperty="bno" order="BEFORE"
   resultType="long">
   select seq_board.nextval from dual
  </selectKey>
insert into board(bno, title, content, writer)
  values (#{bno},#{title},#{content},#{writer})
</insert>
</mapper>

Вставить тест

  • просто нужно создать функцию, потому что картограф существует

Бизнес

  • сделка

например в банке

Транзакции A и B сгруппированы как

  • Деньги уходят со счета А
  • Деньги поступают на счет Б.

если один из них терпит неудачу, сама транзакция терпит неудачу.

Мы делаем то же самое здесь.

Мы группируем услуги в соответствии с использованием веб-сайта.

  1. Создать пакет услуг

2. создать сервисный интерфейс

package org.knr.boardex001.service;
import java.util.List;
import org.knr.boardex001.domain.BoardVO;
public interface BoardService {
 //게시물 등록, 얻기 , 수정 , 삭제, 리스트 얻기 
 //인터페이스니까 추상 메소드로 
 public void register(BoardVO board); 
 public BoardVO get(Long bno); 
 public boolean modify(BoardVO board); 
 public boolean remove(Long bno);
public List<BoardVO> getList();
}

3. Реализовать интерфейс и создать класс

  • импортировать картограф
  • добавить журнал и сервис
package org.knr.boardex001.service;
import java.util.List;
import org.knr.boardex001.domain.BoardVO;
import org.knr.boardex001.mapper.BoardMapper;
import org.springframework.stereotype.Service;
import lombok.AllArgsConstructor;
import lombok.extern.java.Log;
//로그 찍기 위해서 
@Log
//자동으로dependency injection할거라서 component라는 걸 알려줘야 스캔을 해서 만들 수 있음 
@Service
//서비스 객체 생성할때 field자동으로 다 만들어서 주입한다. 
@AllArgsConstructor
public class BoardServicempl implements BoardService {
 // mapper가 있어야함
private BoardMapper boardMapper;
@Override
 public void register(BoardVO board) {
  // TODO Auto-generated method stub
  boardMapper.insert(board);
 }
@Override
 public BoardVO get(Long bno) {
  // TODO Auto-generated method stub
  return boardMapper.read(bno);
 }
@Override
 public boolean modify(BoardVO board) {
  // TODO Auto-generated method stub
  int n = boardMapper.update(board);
  if (n == 1) {
return true;
  } else {
   return false;
  }
}
@Override
 public boolean remove(Long bno) {
  // TODO Auto-generated method stub
  int n = boardMapper.delete(bno);
  if (n == 1) {
return true;
  } else {
   return false;
  }
 }
@Override
 public List<BoardVO> getList() {
  // TODO Auto-generated method stub
  return boardMapper.getList();
 }
}

allargsconstructor

автоматически создавать и вводить поле при создании объекта службы

  • autowire весь маппер внутри.

Создать контроллер

package org.knr.boardex001.controller;
import org.knr.boardex001.domain.BoardVO;
import org.knr.boardex001.service.BoardService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import lombok.AllArgsConstructor;
import lombok.extern.java.Log;
import oracle.net.ano.Service;
@Controller
@Log
@RequestMapping("/board")
@AllArgsConstructor
public class BoardController {
 
 private BoardService service;
 @GetMapping("/list")
 public void list(Model model) {
  log.info("list..........!");
  model.addAttribute("list",service.getList());
 }
 
 @GetMapping("/register")
 public void register() {
 }
 
 @PostMapping("/register")
 public String registerPro(BoardVO board,RedirectAttributes rttr) {
  log.info("registerPro");
  service.register(board);
  rttr.addFlashAttribute("result", board.getBno());
  return "redirect:list";
 }
 
 @GetMapping("/get")
 public void get(Long bno,Model model) {
  log.info("get");
  model.addAttribute("board", service.get(bno));
 }
 @PostMapping("/update")
 public String update(BoardVO board) {
  log.info("update");
  if(service.modify(board)) {
   return "redirect:list";
  }else {
   return "redirect:get";
  }
  
 }
 @GetMapping("/delete")
 public String delete(Long bno) {
  log.info("delete");
  if(service.remove(bno)) {
   return "redirect:list";
  }else {
   return "redirect:get";
  }
 }
 
 
 
}

2. список.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
 <table>
  <tr>
   <th>bno</th>
   <th>title</th>
   <th>writer</th>
   <th>regdate</th>
   <th>updatedate</th>
  </tr>
<c:forEach items="${list }" var="board">
   <tr>
    <td>${board.bno }</td>
    <td>${board.title }</td>
    <td>${board.writer }</td>
    <td><fmt:formatDate value="${board.regdate }" /> </td>
    <td><fmt:formatDate value="${board.updatedate }" /></td>
</tr>
  </c:forEach>
 </table>
</body>
</html>

3.get.jsp

<%@ 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>
 <form action="update" method="post">
  <table>
   <tr>
    <th>번호</th>
    <td><input type="text" name="bno" value="${board.bno}" readonly></td>
   </tr>
   <tr>
    <th>제목</th>
    <td><input type="text" name="title" value="${board.title}"></td>
   </tr>
   <tr>
    <th>내용</th>
    <td><textarea rows="5" cols="50" name="content">${board.content}</textarea></td>
   </tr>
   <tr>
    <th>작성자</th>
    <td><input type="text" name="writer" value="${board.writer}"></td>
   </tr>
   <tr>
    <th>작성일</th>
    <td>${board.regdate}"</td>
   </tr>
   <tr>
    <th>수정일</th>
    <td>${board.updatedate}</td>
   </tr>
   <tr>
    <td colspan="2" align="center"><input type="submit" value="수정">
     <input type="button" value="삭제"
     onclick="location.href='delete?bno=${board.bno}'"> <input
     type="reset" value="취소"></td>
   </tr>
  </table>
 </form>
</body>
</html>

регистрация.jsp

<%@ 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>
 <form action="register" method="post">
  <table>
   <tr>
    <th>제목</th>
    <td><input type="text" name="title"></td>
   </tr>
   <tr>
    <th>내용</th>
    <td><textarea rows="5" cols="50" name="content"></textarea></td>
   </tr>
   <tr>
    <th>작성자</th>
    <td><input type="text" name="writer"></td>
   </tr>
   <tr>
    <td colspan="2" align="center"><input type="submit" value="등록">
     <input type="reset" value="취소"></td>
   </tr>
  </table>
 </form>
</body>
</html>