SpringBoot study notes (b) - Spring surrounding ecosystem

Summary

\quadIn the previous two articles, namely to explain the principles of the IOC containers Spring, and how to create from scratch a Spring container. But the actual work in the light of these is definitely not enough, also need to expand the database, Redis caching, message queues, and so on that basis. So the next step by step from scratch to expand this basic Spring container.

1. Spring container is introduced from the Bean

\quad First, we know that, under normal circumstances, we will be divided into three business logic, both Controller, Service, Dao.

  1. Controller layer to deal with HTTP requests.
  2. Service logic processing for a particular service.
  3. Dao only thing dealing with the database.

2. Increase Mybatis database on the basis of the Spring

2.1 configuration database

\quadStarting introduced Maven dependence, from the official website acquired Maven dependent SpringBoot, followed by introduction of the database, the first database using the simplest way of example H2. The introduction of H2 database Maven relies after, can begin to Spring configuration database, and new resources in the main directory folder, in which the new application.properties file, write basic configuration information:

spring.datasource.url=jdbc:h2:file:C:/Users/catsme/Desktop/my-first-spring
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=org.h2.Driver
复制代码

2.2 introduced FlyWay automatic database migration tool

\quad Database design:

\quad Test data:

User Id Name
User_1 1 Big baby
User_2 2 Erwa
User_3 3 Three baby
User_4 4 Four baby
User_5 5 Five baby
User_6 6 Six baby

Score Id User_id Score
Score_1 1 1 90
Score_2 2 2 91
Score_3 3 3 89
Score_4 4 4 88
Score_5 5 5 92
Score_6 6 6 94
Socre_7 7 2 2
Socre_8 8 4 3
In the resources directory, create db / migration / V1__CreateTables.sql file, write sql statement:
--用户表
create table user(name varchar(200),
id bigint primary key auto_increment);

--成绩表
create table score(
id bigint primary key auto_increment,
user_id bigint,
Score bigint);

insert into user(name,id) values
('大娃',1),('二娃',2),('三娃',3),('四娃',4),('五娃',5),('六娃',6);

insert into score(id,user_id,score) values
    (1,1,90),(2,2,91),(3,3,89),(4,4,88),(5,5,92),(6,6,94),(7,2,2),(8,4,3);
复制代码

Add the following information to the pom.xml for introducing flyway plug-ins:

<plugin>
         <groupId>org.flywaydb</groupId>
         <artifactId>flyway-maven-plugin</artifactId>
         <version>6.0.6</version>
         <configuration>
             <url>jdbc:h2:file:C:/Users/catsme/Desktop/my-first-spring</url>
             <user>root</user>
             <password>password</password>
          </configuration>
 </plugin>
复制代码

Then, use the mvn flyway:migratecommand to initialize the database, the next step is quoted MyBatis complex sql operate.

2.3 Two methods configured by Spring and references MyBatis

  • (A) using the same general approach
    \quadfirst declare an interface:
@Mapper
public interface MyMapper {
    @Select("select * from user where id = #{}")
    User getUser(@Param("id") Integer id);
}
复制代码

\quadNext mapper block config.xml file in the directory mybatis declared interface:
<mapper class="hello.dao.MyMapper"/>. And now can be found, the Spring association of MyBatis, MyBatis associated interface , so the question is, how to achieve this MyMapper next to it?
\quadIt notes the statement by the dependencies between them to achieve this relationship via dependency injection. code show as below:

//使用Autowired注解或者Resource注解注入依赖关系
 @Autowired
    private UserMapper myMapper;

    @RequestMapping("/getUser")
    @ResponseBody
    public User getUser(){
        return myMapper.getUserById(3);
    }
复制代码

Then you can access through this interface in the browser, to achieve access to data in the database.

  • (B) the xml configuration file

\quadNow there is such a demand: in descending order of total score for the user to sort, so, this is not good use to achieve the above through the interface. New config.xml file in the db / mybatis directory, write basic configuration information:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    <typeAliases>
        <typeAlias alias="User" type="hello.entity.User"/>
        <typeAlias alias="ScoreItem" type="hello.entity.ScoreItem"/>
    </typeAliases>
    <mappers>
        <mapper resource="db/mybatis/MyMapper.xml"/>
        <mapper class="hello.dao.UserMapper"/>
    </mappers>
</configuration>
复制代码

\quadNote: Due to the application.properties already been bundled database file basic information, so this time has no need to configure data sources in xml file. Spring in the direct written statement MyBatis code is as follows:
mybatis.config-location=classpath:db/mybatis/config.xml
take the sql statement written in MyBatis mapping file, the code is as follows:

<?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="MyUserMapper">
    <select id="rankUser" resultMap="scoreItem">
        select t.user_id,t.score_sum,user.name as user_name from
        (select user_id,sum(score) as score_sum from score group by user_id)t
        inner join user
        on user.id = t.user_id
        order by t.score_sum
        desc
    </select>

    <!-- 非常复杂的结果映射 -->
    <resultMap id="scoreItem" type="ScoreItem">
        <result property="score" column="score_sum"/>
        <association property="user" javaType="User">
            <result property="name" column="user_name"/>
            <result property="id" column="user_id"/>
        </association>
    </resultMap>
</mapper>
复制代码

\quadHere, the basic information is configured to configure completed, the next is performed, by layering the idea to achieve a corresponding function in the different logical layers. For dao layer, to achieve interaction with the database:

@Service
public class RankDao {

     @Autowired
     SqlSession sqlSession;

     public List<ScoreItem> getRankItem(){
          return sqlSession.selectList("MyUserMapper.rankUser");
     }
}
复制代码

\quadHere you can see, the original need SqlSessionFactory get sqlSession, now just need to declare Autowired in the Spring and then you can call the method of Example sqlSession directly created. Next, create entiy layer entity objects to store data to get from the dao layer, the code:

public class ScoreItem {
    private Integer id;
    private Integer score;
    private User user;

    public Integer getId() {
        return id;
    }

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

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Integer getScore() {
        return score;
    }

    public void setScore(Integer score) {
        this.score = score;
    }
}
复制代码

\quad Business logic in the service layer:

@Service
public class RankService {
    @Autowired
    private RankDao rankDao;


    public List<ScoreItem> sort() {
        return rankDao.getRankItem();
    }
}
复制代码

Finally interact with the user interface in the Controller layer:

@RestController
public class HelloController {

    @Autowired
    private RankService rankService;

    @RequestMapping("/getUser")
    @ResponseBody
    public List<ScoreItem> getUserFromDatabase() {
      return rankService.sort();
    }
}
复制代码

Final results are as follows:

\quad We can see, so from start to finish to achieve a smaller business logic, if coupled with some rendering, it can become a real page.

3. rendering HTML

\quad After out data from the database, the next step is to render the page, the front end with the rear end of this process can be achieved.

3.1 back-end rendering FreeMarker

\quadWhat is a template engine does, from Baidu Encyclopedia explained: template engine (here especially for Web development template engine) is to make the user interface and business data (content) resulting from the separation, it can generate a document in a specific format, the template engine for the site will generate a standard HTML document. As used herein, FreeMarker tool to render the page.
\quadWhat is FreeMarker does, from Wikipedia to explain: FreeMarker is a Java-based template engine, originally focused on using the MVC software architecture to generate dynamic web pages. However, it is a generic template engine does not rely on or HTTP servlets or HTML, so it is often used to generate source code, configuration files or e-mail.
\quadSo we can generate HTML pages by FreeMarker. FreeMarker introduction of mavne dependent , suggesting that according to the official website:

resources
        ├── application.yml
        ├── data-h2.sql
        ├── schema-h2.sql
        ├── static
        │   └── css
        │       └── style.css
        └── templates   
            ├── index.ftl
            └── showCities.ftl
复制代码

\quadWe need to create a templates folder under the resources directory, so by default will look for FreeMarker templates folder. Then create index.ftl file, written in addition to the initial format .ftl template file, then the contents of which passed. .ftl file written codes in HTML format:

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>成绩排行榜</title>
    </head>
    <body>
    <table>
        <thead>
        <tr>
            <th>用户号码</th>
            <th>成绩</th>
            <th>用户名</th>
        </tr>
        </thead>
        <tbody>
        <tr>
            <td>${index}</td>
            <td>${name}</td>
            <td>${score}</td>
        </tr>
        </tbody>
    </table>
    </body>
    </html>
复制代码

\quadAfter this custom templates HTML document rendering good, it is to find ways in which the incoming data. Similar to MyBatis code is as follows:

    @RequestMapping("/getUser")
    @ResponseBody
    public ModelAndView getUserFromDatabase() {
        Map<String, Object> model = new HashMap<>();
        model.put("index",1);
        model.put("name","zhangsan");
        model.put("score",97);
        //接受两个参数,一个模板文件一个数据
        return new ModelAndView("index",model);
    }
复制代码

result:

\quad This can be seen when we passed through parameters to the template file, to achieve a rendering of the page. This is just test results, in fact, we need to loop through the content to show up. Then the next step is to put the database in real data out, put the page. The question is: to get data from the database is six, then to achieve the cycle rendering it? Check FreeMarker official website after the modification of the code template file:

<thead>
    <tr>
        <th>序号</th>
        <th>成绩</th>
        <th>姓名</th>
        <th>学号</th>
    </tr>
    </thead>
    <tbody>

    <#list items as item>
         <tr>
            <td>${item?index+1}</td>
            <td>${item.user.name}</td>
            <td>${item.score}</td>
            <td>${item.user.id}</td>
         </tr>
    </#list>
    </tbody
复制代码

Achieve results:

3.2 front-end rendering JSON and JS

\quadHere is the original front-end can be directly performed JS framework design, but in order to deepen the understanding of the front and rear end rendering (in fact he will not), so use the most primitive way, do not work with! ! !
\quadNew static folder under the resources directory, the contents of this folder can be accessed directly. In which the new index.html page document, written in the document:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>成绩排行榜</title>
</head>
<body>
<table id="rank-table">
    <thead>
    <tr>
        <th>序号</th>
        <th>成绩</th>
        <th>姓名</th>
        <th>学号</th>
    </tr>
    
    </thead>
    <tbody>
    
    </tbody>
</table>
</body>
</html>
复制代码

This time can be accessed through a browser directly index.html:

Then added in html script tag, to send http request:

<script>
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
          if( xhr.readyState == 4){
             if( xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
             var json = xhr.responseText;
             <!--后将获取的结果打印至控制台-->
             console.log(json);
          }
       }
    };
     <!--先通过getRankItem接口发送请求-->
        xhr.open("get", "/getRankItem", true);
        xhr.send(null);
    </script>
复制代码

Then you can see the JSON string acquired in the browser:

\quad What is needed now is the result script tag via javascript acquired, spliced into the html to show on the page. Note: Do not do real work! Buying and learning, using the most basic way to achieve string concatenation, and then written in html:

<script>
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
          if( xhr.readyState == 4){
             if( xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
             var json = xhr.responseText;
             var list = JSON.parse(json);
             var str1 = '';
             var step;
             for (step = 0; step < 5; step++) {
                str1 += '<tr><td>'+(step+1)+'</td><td>'+list[step].score+'</td><td>'+list[step].user.name+'</td><td>'+list[step].user.id+'</td></tr> '
             }

             var str = '<tr><th>序号</th><th>成绩</th><th>姓名</th><th>学号</th>'+str1+
             '<tr><td>6</td><td>'+list[5].score+'</td><td>'+list[5].user.name+'</td><td>'+list[5].user.id+'</td></tr>'

          document.getElementById('rank-table').innerHTML = str;
          }
       }
    };
        xhr.open("get", "/getRankItem", true);
        xhr.send(null);

    </script>
复制代码

Achieve results is as follows:

4. resolve error

4.1 mvn flyway:migrateCommand error:

-> Applied to database : 1062144176
-> Resolved locally : 1432425380
复制代码

This situation requires deleting records in the database:

4.2 code checking tool always reported File does not end with a newline.'error

\quad Delete the directory under .circle

 <module name="NewlineAtEndOfFile">
        <property name="lineSeparator" value="lf" />
    </module>
复制代码

It can be.

Project Address: github.com/Scott-YuYan...

5. References

  1. Nuggets. "How should your project stratified correct? " Click here to view the source document

  2. CSDN "Flyway Validate failed: migration checksum mismatch for migration 1.0.0003" Click here to view the source document

Guess you like

Origin juejin.im/post/5dc51da7e51d452bff030cd6