1. 程式人生 > >構建web應用之——SpringMVC實現CRUD

構建web應用之——SpringMVC實現CRUD

配置好SpringMVC最基本的配置後,開始實現處理資料的CRUD(CREATE, READ, UPDATE, DELETE)

為實現模組上的鬆耦合,我們將與資料庫的互動任務交給DAO(Data Access Object,即資料訪問物件)層,

SpringMVC中使用@Repository註解為DAO自動生成bean,下面是實現資料增刪改查所用的資料庫:

1.資料庫:mysql

2.資料來源連線池:DBCP(最先使用了Spring中內建的基於JDBC的資料來源DriverManagerDataSource,但它沒有

池的概念,在每次請求連線時都要建立新連線,降低了效能)

實現過程:

一、新增依賴

基於之前的專案,我們還需要配置一些其他的依賴,來支援我們專案的構建,具體依賴如下:

<!-- mysql -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.1.3.RELEASE</version>
    </dependency>
    <dependency
> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.13</version> <scope>runtime</scope> </dependency> <!-- 資料來源連線池 --> <dependency> <groupId>commons-dbcp</
groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>commons-pool</groupId> <artifactId>commons-pool</artifactId> <version>1.6</version> </dependency>

除了上述依賴意外,我們還需要加入spring bean的依賴。雖然我們使用註解自動裝配以及XML配置的形式來宣告和使用bean,

但是,我們需要spring bean來配置我們的配置檔案路徑。

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>5.1.3.RELEASE</version>
    </dependency>

二、編碼(Service層和Controller層的實現)

我們通過DAO層來與資料庫實現互動,因此,我們的Service層以及Controller層無需關注資料互動,只需要處理自己本職的工作即可。

下面是檔案結構:

我們通過StudentController類來響應請求,通過StudentService介面來定義CRUD四種服務,通過StudentDao介面來定義

與資料庫互動的方法(增、刪、改、查),StudentServiceImpl類以及StudentDaoImpl類分別實現了介面中定義的方法。

StudentDao定義與資料庫互動的方法(具體實現過程拋給其實現類):

package example.dao;

import example.entity.Student;

public interface StudentDao {

    public void create(Student student);
    public Student readById(String studentId);
    public void updateName(String studentId, String newUsername);
    public void deleteById(String studentId);
}

有了StudentDao中定義的方法後,我們就可以編寫Controller層和Service層程式碼邏輯了(資料如何增刪改查我們暫時不用關心)

StudentService定義了我們的web專案所要擁有的功能:

1.新增一個學生

2.查詢指定學號的學生資訊

3.更新學生資訊

4.刪除指定學生

package example.service;

import example.entity.Student;

public interface StudentService {

    public void create(Student student);
    public Student readById(String studentId);
    public void updateUsername(String studentId, String newName);
    public void deleteById(String studentId);

}

StudentServiceImpl實現了StudentService介面中的方法

package example.service;

import example.dao.StudentDao;
import example.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Service;

@Service
public class StudentServiceImpl implements StudentService {

    // 注入StudentDao
    @Autowired
    private StudentDao studentDao;

    @Override
    public void create(Student student) {
        studentDao.create(student);
    }

    @Override
    public Student readById(String studentId) {
        return studentDao.readById(studentId);
    }

    @Override
    public void updateUsername(String studentId, String newName) {
        studentDao.updateName(studentId, newName);
    }

    @Override
    public void deleteById(String studentId) {
        studentDao.deleteById(studentId);
    }
}

使用@Service註解使得Spring自動為StudentService生成bean,同時我們注入了StudentDao的bean

Controller層負責處理請求:

package example.controller;

import example.entity.Student;
import example.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;


@Controller
@RequestMapping("/student")
public class StudentController {

    // 注入StudentService Bean
    @Autowired
    private StudentService studentService;

    // 處理建立學生請求
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public String createStudent(Student student) {
        studentService.create(student);
        // 重定向到學生資訊介面
        return "redirect:/student/read/" + student.getStudentId();
    }

    // 處理查詢學生資訊請求
    @RequestMapping(value = "/read/{studentId}", method = RequestMethod.GET)
    public String readStudent(
            @PathVariable("studentId") String studentId,
            Model model) {
        model.addAttribute(studentService.readById(studentId));
        return "student";
    }

    // 處理JSP檢視查詢處理
    @RequestMapping(value = "/read", method = RequestMethod.GET)
    public String readStudentByView(
            @RequestParam("studentId") String studentId,
            Model model) {
        model.addAttribute(studentService.readById(studentId));
        return "student";
    }

    // 處理修改學生資訊請求
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public String updateStudent(String studentId, String newUsername) {
        studentService.updateUsername(studentId, newUsername);
        return "redirect:/student/read/" + studentId;
    }

    // 處理刪除學生請求
    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    public String deleteStudent(String studentId) {
        studentService.deleteById(studentId);
        return "deleteSuccessfully";
    }
}

@Controller註解使Spring自動為其生成bean,@RequestMapping註解用來宣告請求對映(類比之前的helloMVC實現)

最後,我們需要在DispatcherServlet以及Spring內部配置檔案中進行配置,使其能夠在編譯時掃描到帶有註解的類併為其生成bean

dispatcher-servlet.xml中

<!-- DispatcherServlet上下文只管理@Controller型別的bean -->
    <context:component-scan base-package="example">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
<!-- 自動掃描裝配 -->
    <context:component-scan base-package="example.controller"/>

applicationContext.xml

<!-- 忽略對@Controller的掃描 -->
    <context:component-scan base-package="example">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

 

三、實現Dao層

到目前為止,我們還無法獲取資料(當然可以在StudentDaoImpl中使用靜態資料),接下來我們要實現StudentDao介面中

的方法,使得我們能真正意義上在檢視中看到想要的資料

在編寫方法邏輯之前,我們需要完成資料庫相關配置:

1.資料庫配置引數(jdbc.properties)鬆耦合的一種方式

############ DBCP資料來源連線池配置
############ mysql
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
jdbc.username=root
jdbc.password=
############ BasicDataSource的池配置屬性
jdbc.initialSize=5
jdbc.maxActive=10

2.完成資料庫、資料來源以及bean的裝配

<!-- Spring內建JDBC資料來源 -->
    <!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/student?useUnicode=true&amp;characterEncoding=utf8
            &amp;serverTimezone=GMT"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
    </bean> -->

    <!-- 配置jdbc.properties路徑 -->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties"/>
    </bean>
    <!-- 使用DBCP資料來源連線池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="initialSize" value="${jdbc.initialSize}"/>
        <property name="maxActive" value="${jdbc.maxActive}"/>
    </bean>

    <!-- 使用JDBC模板操作資料 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg ref="dataSource"/>
    </bean>

注意:配置連線資料庫的引數變數時,不能只寫url,username等,應為xml中使用${username}獲得的是計算機賬號的名稱,要加以區分

3.實現StudentDao方法

這一部分說白了就是編寫增刪改查的SQL語句,程式碼如下:

package example.dao;

import example.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import java.sql.ResultSet;
import java.sql.SQLException;

@Repository
public class StudentDaoImpl implements StudentDao {

    private JdbcTemplate jdbcTemplate;

    @Autowired
    public StudentDaoImpl(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    private static final String INSERT_STUDENT =
            "insert into student (student_id, student_name, password)" +
                    "values (?, ?, ?)";

    private static final String QUERY_STUDENT =
            "select student_id, student_name, password from student where student_id = ?";

    private static final String UPDATE_STUDENT =
            "update student set student_name = ? where student_id = ?";

    private static final String DELETE_STUDENT =
            "delete from student where student_id = ?";

    @Override
    public void create(Student student) {
        jdbcTemplate.update(INSERT_STUDENT,
                student.getStudentId(),
                student.getUsername(),
                student.getPassword());
    }

    @Override
    public Student readById(String studentId) {
        return jdbcTemplate.queryForObject(
                QUERY_STUDENT,
                new StudentRowMapper(),
                studentId
        );
    }

    @Override
    public void updateName(String studentId, String newUsername) {
        jdbcTemplate.update(UPDATE_STUDENT,
                newUsername,
                studentId);
    }

    @Override
    public void deleteById(String studentId) {
        jdbcTemplate.update(DELETE_STUDENT, studentId);
    }

    private static final class StudentRowMapper
            implements RowMapper<Student> {
        @Override
        public Student mapRow(ResultSet resultSet, int i) throws SQLException {
            return new Student(
                    resultSet.getString("student_id"),
                    resultSet.getString("student_name"),
                    resultSet.getString("password")
            );
        }
    }
}

使用@Repository註解使得Spring能夠自動生成StudentDao的bean,同時注入JDBCTemplatebean用於資料庫sql的操作,

需要注意的是,呼叫JdbcTemplate.queryForObject()方法時,需要一個RowMapper物件用於存放查詢的Student物件,因此,

在程式碼最後我們定義了一個內部類實現了RowMapper介面,並實現了mapRow()方法用於返回一個Student的例項

以上,我們的程式碼實現就完成了。要執行web專案,我們還需要在Mysql資料庫中建立student表以及建立相關檢視

home.jsp

<%--
  Created by IntelliJ IDEA.
  User: asus1
  Date: 2019/1/6
  Time: 12:06
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    Hello world! Hello SpringMVC!
    <div>
        create:
        <form action="http://localhost:8080/trymaven/student/create" method="post">
            studentId: <input type="text" name="studentId" placeholder="studentId"/>
            username: <input type="text" name="username" placeholder="username"/>
            password: <input type="password" name="password" placeholder="password"/>
            <input type="submit" value="submit"/>
        </form>
    </div>
    <div>
        read:
        <form action="http://localhost:8080/trymaven/student/read" method="get">
            studentId: <input type="text" name="studentId" placeholder="studentId"/>
            <input type="submit" value="submit">
        </form>
    </div>
    <div>
        update:
        <form action="http://localhost:8080/trymaven/student/update" method="post">
            studentId: <input type="text" name="studentId" placeholder="studentId"/>
            new username: <input type="text" name="newUsername" placeholder="new username"/>
            <input type="submit" value="submit"/>
        </form>
    </div>
    <div>
        delete:
        <form action="http://localhost:8080/trymaven/student/delete" method="post">
            studentId: <input type="text" name="studentId" placeholder="studentId"/>
            <input type="submit" value="submit"/>
        </form>
    </div>
</body>
</html>

student.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: asus1
  Date: 2019/1/6
  Time: 19:39
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>student</title>
</head>
<body>
    <div class="studentView">
        <span class="studentId"><c:out value="${student.studentId}"/></span>
        <span class="studentName"><c:out value="${student.username}"/></span>
    </div>
</body>
</html>

deleteSuccessfully.jsp

<%--
  Created by IntelliJ IDEA.
  User: asus1
  Date: 2019/1/6
  Time: 19:45
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>deleteState</title>
</head>
<body>
The information is deleted successfully.
</body>
</html>

四、執行web專案

通過Tomcat啟動專案: