[SSM oriented CRUD programming column 9] SSM framework integration

πŸ›« For more ssm knowledge, see SSM_ CRUD oriented programming column

πŸš• This blog summarizes from the ssm framework video of dark horse programmer

πŸš’ Bloggers are still learning this knowledge

πŸš„ If you find any problems, please point them out

πŸš€πŸš€Zhawatai zaogao's blog home pageπŸš€πŸš€

catalogue

πŸ”’ case analysis

πŸ”‘ Frame structure

​ πŸ”“ realization

If the interview is like making an aircraft carrier, and the job is to screw in screws, then the SSM framework is a screwdriver that is very suitable for beginners to lay the foundation.

-- Lu Xun

In the previous study of the knowledge of ssm column, we have made it clear that the ssm framework is composed of three frameworks - spring, spring MVC and MyBatis. These three frameworks have saved us a lot of development time. What we need to do now is to integrate these three frameworks together so that they can better cooperate and save us more development time.

πŸ”’ case analysis

Since this blog is mainly to explain the integration knowledge of ssm framework, a relatively simple case is prepared. The project needs to connect to the database to realize two functions: inserting data on the page, querying data and displaying it on the page.

πŸ”‘ Frame structure

In the src/main/java directory of the project, the ssm framework generally contains four package s, which are often called four layers. From the order of daily development, it is divided into domain layer (also known as entity layer), mapper layer (also known as dao layer), service layer and controller layer. There will also be five layers of complexity, with one more until layer. Due to the limited learning time, we don't know the more complex situation πŸ˜“In addition to the domain layer, the other three layers have corresponding configuration files to cooperate with the use of spring framework code, and finally in the web Load the configuration file into the XML file, otherwise the configuration file is equivalent to white configuration and will not take effect. In addition to the above configuration file correspondence, another way is to synthesize spring XXX into an ApplicationContext XML, which can reduce the number of configuration files, but the corresponding relationship is not clear. Of course, the configuration file changes the web The XML file will also change. This case will be explained in the second corresponding way.

πŸ”“ realization

πŸ– Project hierarchy

If you won't create a web project, refer to previous blogs for creation [download tutorials on how to create a full set of SSM programming modules for programmers, and skip the most questions about how to install SSM

πŸ₯©pom.xml

<dependencies>
    <!--spring relevant-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.7</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.0.5.RELEASE</version>
    </dependency>

    <!--servlet and jsp-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.0</version>
    </dependency>

    <!--mybatis relevant-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.1</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>

    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

</dependencies>

πŸ• domain layer

For the entity class corresponding to the account table in the database, first create a database table with reference to the following figure

Create an Account class under the domain layer to correspond to each field in the database

public class Account {

    private Integer id;
    private String name;
    private Double money;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }
}

πŸ” mapper layer

I have learned the agent development mode of MyBatis before. If I use this mode for development, I no longer need to implement classes, but I need to meet the following four conditions

  • namespace of mapper tag = fully qualified name of the interface
  • Interface method = id of mapper word label
  • Interface method parameter type = parameterType of mapper word label
  • Return value type of interface method = resultType of mapper label

The mapper layer creates an AccountMapper interface to define the implementation method of insertion and query functions

public interface AccountMapper {

    public void save(Account account);

    public List<Account> findAll();

}

Create accountmapper The XML Mapping file uses SQL statements to operate on the database

<?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.itheima.mapper.AccountMapper">

    <insert id="save" parameterType="account">
        insert into account values(#{id},#{name},#{money})
    </insert>

    <select id="findAll" resultType="account">
        select * from account
    </select>

</mapper>

To connect to the database, you need to extract the configuration of the database to JDBC In properties, it is convenient to modify in the future (the value on the right of the equals sign should be configured into the value of its own database), which is also called decoupling

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=123456

After having the database configuration, you need to use applicationcontest To configure data source information in XML, of course, you need to load the above database configuration first, that is, to create a connection pool. I believe you all know the benefits of connection pool

<!--load propeties file-->
<context:property-placeholder location="classpath:jdbc.properties"/>

<!--Configure data source information-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driver}"></property>
    <property name="jdbcUrl" value="${jdbc.url}"></property>
    <property name="user" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>

The following service layer needs to use the AccountMapper object to call its methods, so we need to use the spring framework to directly create the object at the bottom and then inject the service directly. In this case, we need to use applicationcontest Let the spring framework know in XML that it needs to do this

<!--to configure sessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <!--load mybatis Core document-->
    <property name="configLocation" value="classpath:sqlMapConfig-spring.xml"></property>
</bean>

<!--scanning mapper The package is mapper Create implementation class-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.itheima.mapper"></property>
</bean>

Database operation is also called transaction. Since there is a transaction, it should be in applicationcontest XML has declarative transaction control over it

<!--Declarative transaction control-->
<!--Platform transaction manager-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!--Configure transaction enhancements-->
<tx:advice id="txAdvice">
    <tx:attributes>
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

<!--Transactional aop Weave in-->
<aop:config>
    <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service.impl.*.*(..))"></aop:advisor>
</aop:config>

🍟 service layer

The service layer has an AccountService interface. Generally speaking, it is the same as the AccountMapper interface because it describes the business requirements, that is, what functions need to be completed

public interface AccountService {

    public void save(Account account);

    public List<Account> findAll();

}

There is an Implpackage under the service layer, which is used to put all interface implementation classes, such as the AccountServiceImpl class of this case. The object of a previously created AccountMapper can be injected directly through annotations and then invoked.

@Service("accountService")
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapper;

    public void save(Account account) {
        accountMapper.save(account);
    }

    public List<Account> findAll() {
        return accountMapper.findAll();
    }
}

The @ Service annotation is used here, so it needs to be in applicationcontest XML scans the annotations to let the framework know that the corresponding object should be created

<!--Component scan service and mapper-->
<context:component-scan base-package="com.itheima">
    <!--exclude controller Scan of-->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter>
</context:component-scan>

🌭 controller layer

The controller layer is a layer that interacts with the front end and determines the specific matters of request and response. Let's put the code first and then explain it in detail

@Controller
@RequestMapping("/account")
public class AccountController {

    @Autowired
    private AccountService accountService;

    // Save data
    @RequestMapping(value = "/save", produces = "text/html;charset=UTF-8")
    @ResponseBody
    public String save(Account account){
        accountService.save(account);
        return "Saved successfully";
    }

    //Query data
    @RequestMapping("/findAll")
    public ModelAndView findAll(){
        List<Account> accountList = accountService.findAll();
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("accountList",accountList);
        modelAndView.setViewName("accountList");
        return modelAndView;
    }

}

The @ controller annotation is used here, so it needs to be in spring MVC XML configures the annotation driver and scans the annotation to let the framework know that the corresponding object should be created

<!--Component scan main scan controller-->
<context:component-scan base-package="com.itheima.controller"/>

<!--to configure mvc Annotation driven-->
<mvc:annotation-driven/>

@The RequestMapping annotation sets the mapping address of the method. When the front end accesses the mapping address, the corresponding method will be executed. The annotation on the class and the annotation on the method correspond to two different mapping paths respectively, that is, when the current end sends the / account/save request, the save method will be called. The produces property sets the encoding format of the response to prevent garbled code when a string is returned to the page

@The ResponseBody annotation indicates that only a string is returned instead of page Jump. If it is page Jump, you need to open the access permission of static resources (jsp page), which can also be found in spring MVC Configure the view parser in XML and add prefix and suffix to the return value (because the front-end pages during development will be placed under a unified package, and the page suffix is basically jsp, so the code writing during development can be reduced)

<!--Open access to static resources-->
<mvc:default-servlet-handler/>

<!--Internal resource view parser-->
<bean id="resourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/"></property>
    <property name="suffix" value=".jsp"></property>
</bean>

jsp page for storing data

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>Add account information form</h1>
    <form name="accountForm" action="${pageContext.request.contextPath}/account/save" method="post">
        title of account:<input type="text" name="name"><br>
        Account amount:<input type="text" name="money"><br>
        <input type="submit" value="preservation"><br>
    </form>
</body>
</html>

Query the jsp page corresponding to the data

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>Display account data list</h1>
    <table border="1">
        <tr>
            <th>account id</th>
            <th>title of account</th>
            <th>Account amount</th>
        </tr>

        <c:forEach items="${accountList}" var="account">
            <tr>
                <td>${account.id}</td>
                <td>${account.name}</td>
                <td>${account.money}</td>
            </tr>
        </c:forEach>

    </table>
</body>
</html>

🍿 web.xml file

Load ApplicationContext XML file

<!--spring monitor-->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Load spring MVC XML file, also known as front-end controller

<!--springmvc Front end controller-->
<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

Configure the global filter to solve the problem of garbled POST requests

<!--Global filter is used to solve the problem of garbled code-->
<filter>
    <filter-name>CharacterEncodingFilter</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>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

So far, the framework integration of ssm has come to an end. Every craftsman in a big country starts from basic learning, so he can be different from ordinary people. In addition to talent, it is to consolidate basic skills, coupled with the precipitation of time and the accumulation of experience. Ten thousand tall buildings rise from the ground, which is the first stop of frame development.

Β  Β  Β 

Previous: [SSM programming for CRUD column 8] a blog quickly started CRUD using MyBatis

Next: to be continued

Keywords: Java Back-end SSM

Added by tecmeister on Sun, 06 Feb 2022 10:28:40 +0200