企业级博客项目笔记(一)

企业级博客项目笔记(一)

一、Gradle测试

1.编写项目构建信息

初始化helloworld项目:可以复制基础项目的gradle、src 、.gitignore、build.gradle、gradlew、gradlew.bat文件

  • 编辑build.gradle文件:修改version版本号
  • 编译项目:gradle build
  • 启动项目:java -jar 项目jar包

2.自定义存储库,加速构建

  • 修改build.gradle文件:repositories中的值改为 url 'http://maven.aliyun.com/nexus/content/groups/public'

3.编写程序代码

  • 编写HelloController.java和HelloControllerTest.java

4.配置Gradle Wrapper

  • 修改gradle/wrapper/gradle-wrapper.properties配置文件
  • gradle/wrapper下的jar包是wrapper的应用程序
  • gradle-wrapper.properties配置文件中的distributionUrl是gradle安装包的官方地址
  • gradlew.bat是在windows下执行的wrapper脚本:gradlew build使用wrapper编译项目

二、开发环境的搭建

1.安装、配置IDE

  • jdk、gradle、eclipse

2.导入项目、运行

  • 设置发布包的位置:默认Gradle wrapper
  • 第一次导入项目,会有依赖包下载
  • 三种运行方式:1.使用java -jar命令 2.以javaApplication.java运行 3.Spring Boot Gradle Plugin 插件启动:gradle bootRun/gradlew bootRun

3.扩展学习

  • 常用Eclipse插件:https://github.com/waylau/everything-in-eclipse

三、集成Thymeleaf

1.Thymeleaf

  • 概念:Java模板引擎,能够处理HTML、XML、JavaScript、CSS甚至纯文本。类似JSP、Freemarker
  • 优点:自然模板。原型即页面;语法优雅易懂。OGNL、SpringEL;遵从Web标准。支持HTML5;

2.如何识别Thymeleaf标准方言

  • <span th:text="..."> ---比较常用,需要引入名称空间
    <html xmln:th="http://www.thymeleaf.org">
  • <span data-th-text="..."> ---html5标准,自定义属性

3.变量表达式

  • 语法:${...}
    <span th:text="${book.author.name}">

4.消息表达式

  • 语法:#{...} 
    <table> 
    ...
    <th th:text="#{header.address.city}">..</th>
    <th th:text="#{header.address.country}">...</th> 
    ...
    </table>
  • 消息表达式也称之为文本外化、国际化或i18n

5.选择表达式

  • 语法:*{...}
    <div th:object="${book}">
    ...
    <span th:text="*{title}">...</span> 
    ... 
    </div>
  • 与变量表达式的区别:它们是在当前选择的对象而不是整个上下文变量映射上执行

6.链接表达式

  • 语法:@{...}
    链接表达式可以是相对的,在这种情况下,应用程序上下文将不会作为URL的前缀 
    <a th:href="@{../documnets/report}">...</a>
    也可以是服务器相对(同样,没有应用程序上下文前缀)
    <a th:href="@{~/contents/main}">...</a> 和协议相对(就像绝对URL,但浏览器将使用在显示的页面中使用的相同的HTTP或HTTPS协议)
    <a th:href="@{//static.mycompany.com/res/initial}">...</a>

7. 分段表达式

  • 语法:th:insert或th;replace
    <div th:fragment="copy"/>
    © 2017 <a href="https://waylau.com">waylau.com</a>
    </div>
    <div th:insert="~{footer :: copy}"></div> //表示重用上述代码片段

8.字面量(文字)

  • 文本(使用单引号)
    <p> Now you are looking at a <span th:text="'working web application'">template file</span></p>
  • 数字(直接放在双引号中,可以进行运算)<p>The year is <span th:text="2013">1492</span>.</p>
    <p>In two years,it will be <span th:text="2013+2">1494</span>.</p>
  • 布尔(false/true)
  • null
  • 算术操作:+、-、*、/、%
  • 比较和等价:

比较:>、<、>=、<=(gt、lt、ge、le) <防止与<>出现冲突>
等价:==、!=(eq、ne)

  • 条件运算符: 
    <tr th:class="${row.even}? 'even':'odd'">...</tr>
  • 无操作:(_) <span th:text="${user.name} ?:_">no user authenticated</span>

9.设置属性值

  • 设置任意属性值 th:attr 
    <form action="subscribe.html" th:attr="action=@{/subscribe}"> 
      <fieldset> 
        <input type="text" name="email" /> 
        <input type="submit" value="Subscribe!"th:attr="value=#{subscribe.submit}" /> 
      </fieldset> 
    </form>
  • 设置值到指定的属性 
    <form action="subscribe.html" th:action="@{/subscribe}"> 
    <input type="submit" value="Subscribe!" th:value="#{subscribe.submit}" />
  • 固定值布尔属性 
    <input type="checkbox" name="option2" checked /> <!--HTML--> <input type="checkbox" name="option1" checked="checked" /> <!--XHTML--> 
    thymeleaf中:<input type="checkbox" name="active" th:checked="${user.active}"/>

10.迭代器

  • 基本的迭代th:each (适用于数组、集合、Map) 
    <li th:each="book : ${books}" th:text="${book.title}">En las Orillas del Sar</li>
  • 状态变量 (index、count、size、current、even/odd、first、last) 
    <tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">

11.条件语句

  • th:if 、th:unless (unless与if相反) 
    <a href="comments.html" 
      th:href="@{/product/comments(prodId=${prod.id})}"   th:if="${not #lists.isEmpty(prod.comments)}">view</a>
  • switch 
    <div th:switch="${user.role}"> 
      <p th:case="'admin'">User is an administrator</p> 
      <p th:case="#{roles.manager}">User is a manager</p> 
      <p th:case="*">User is a some other thing</p> 
    </div>

12.Thymeleaf模板布局

  • 定义和引用片段

定义片段:
<div th:fragment="copy"> ©2017<a href="https://waylau.com">waylau.com</a> 
</div> 
引用片段: 
<div th:insert="~(footer :: copy)"></div>

  • 不使用th:fragment定义片段 
    <div id="copy-section"> 
    © 2017<a href="https://waylau.com">waylau.com</a> 
    </div>
  • 不使用th:fragment引用片段 
    <div th:insert="~(footer :: #copy-section)"></div>
  • th:insert、th:replace、th:include三者的区别:
    • th:insert 它将简单地插入指定的片段作为正文的主标签。
    • th:replace 用指定实际片段来替换其主标签。
    • th:include 类似于th:insert,但不是插入片段它只插入此片段的内容。(3.x版本后,不再推荐使用)
  • 属性优先级(Thymeleaf中有规定th:属性的优先级问题) 
     当在同一个标签中写入多th:*属性时,会发生什么? 
     <ul> 
      <li th:each="item:${items}" th:text="${item.description}">Item description here...</li> 
     </ul>

13.注释

  • Thymeleaf解析器级注释块
    • 删除<!--/*--> 和<!--*/-->之间的所有内容
  • 原型注释块
    • 当模板静态打开时(比如原型设计),原型注释块所注释的代码将被注释,而在模板执行时,这些注释的代码,就能被显示出来。 <span>hello!</span> 
      <!--/*/ 
      <div th:text="${...}"> 
      ... 
      </div> 
      /*/--> 
      <span>goodbye!</span>

14.内联

  • 内联表达式 
    [[...]]或[(...)]分别对应于th:text和th:utext 
    注:utext不对内容进行转义 
    <p>The message is "[(${msg})]"</p> ----》文本中的特殊符号不会被转义
  • 禁用内联 
    有时需要禁用这种机制,比如,想输出[[...]]或[(...)]文本内容 
    <p th:inline="none">A double array looks like this:[[1,2,3],[4,5]]!</p>
  • JavaScript内联 
    <script th:inline="javascript">
  • CSS内联 
    <style th:inline="css"> 
    .[[${classname}]]{ 
    text-align:[[${align}]]; 
    } 
    </style>

15.表达式的基本对象

  • 基本对象
    • #ctx:上下文对象。是org.thymeleaf.context.IContext或者org.thymeleaf.context.IWebContext的实现
    • #locale:直接访问与java.util.Locale关联的当前请求
  • request/session等属性
    • param:用于检索请求参数
    • session:用于检索session属性
    • application:用于检索application/servlet上下文属性
  • Web上下文对象
    • #request: 直接访问与当前请求关联的javax.servlet.http.HttpServletRequest对象
    • #session: 直接访问与当前请求关联的javax.servlet.http.HttpSession对象
    • #servletContext:直接访问与当前请求关联的javax.servlet.ServletContext对象

16.配置环境

  • 配置环境
    • Thymeleaf3.0.3.RELEASE
    • Thymeleaf Layout Dialect 2.2.0
  • 修改build.gradle
    //依赖关系 
    dependencies{ 
    ... 
    //添加Thymeleaf的依赖 
    compile('org.springframework.boot:spring-boot-starter-thymeleaf') 
    ... 
    } 
    buildscript{ 
    ... 
    //自定义Thymeleaf 和Thymeleaf Layout Dialect的版本 
    ext['thymeleaf.version']='3.0.3.RELEASE' 
    ext['thymeleaf-layout-dialect.version']='2.2.0' 
    ... 
    }

四、Thymeleaf实战

1. 修改application.properties

#设置编码方式 
  spring.thymeleaf.encoding=UTF-8 
#热部署静态文件 
  spring.thymeleaf.cache=false 
#使用HTML5标准 
  spring.thymeleaf.mode=HTML5

2.API设计(一个Demo,并不遵循Restful风格)

  • GET /users: 返回用于展现用户列表的list.html页面;
  • GET /users/{id}: 返回用于展现用户的view.html页面;
  • GET /users/form: 返回用于新增或者修改用户的form.html页面;
  • POST /users: 新增或者修改用户,成功后重定向到list.html页面;
  • GET /users/delete/{id}: 根据id删除相应的用户数据,成功后重定向到list.html页面;
  • GET /users/modify/{id}: 根据id获取相应的用户数据,并返回form.html页面来执行修改。

3.Demo代码

  • User.java
public class User {
    private Long id; //实体的唯一标识
    private String name; //用户名称
    private String email; //用户邮箱    

    public User(){
    }

    public User(Long id,String name,String email){
        this.id=id;
        this.name=name;
        this.email=email;
    }

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}
  • UserRepository.java
public interface UserRepository {
    /**
     * 创建或者修改用户
     * @param user
     * @return
     */
    User saveOrUpdateUser(User user);

    /**
     * 删除用户
     * @param id
     */
    void deleteUser(Long id);

    /**
     * 根据id查询用户
     * @param id
     * @return
     */
    User getUserById(Long id);

    /**
     * 获取用户列表
     * @return
     */
    List<User> listUsers();
}
  • UserRepositoryImpl.java
@Repository
public class UserRepositoryImpl implements UserRepository {

    private static AtomicLong counter=new AtomicLong(); //用于计数
    private final ConcurrentMap<Long,User> userMap=new ConcurrentHashMap<>();//存储用户信息

    @Override
    public User saveOrUpdateUser(User user) {
        Long id=user.getId();
        if(id==null){
            id=counter.incrementAndGet(); //从计数器中获取一个long型数据
            user.setId(id);
        }
        this.userMap.put(id,user);
        return user;
    }

    @Override
    public void deleteUser(Long id) {
        this.userMap.remove(id);
    }

    @Override
    public User getUserById(Long id) {
        return this.userMap.get(id);
    }

    @Override
    public List<User> listUsers() {
        return new ArrayList<>(this.userMap.values());
    }
}
  • UserController.java
@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserRepository userRepository;

    /**
     * 获取用户列表
     * @param model
     * @return
     */
    @GetMapping
    public ModelAndView list(Model model){
        model.addAttribute("userList",userRepository.listUsers());
        model.addAttribute("title","用户管理");
        return new ModelAndView("users/list","userModel",model);
    }

    /**
     * 根据id查询用户
     * @param id
     * @param model
     * @return
     */
    @GetMapping("{id}")
    public ModelAndView view(@PathVariable("id")Long id, Model model){
        User user=userRepository.getUserById(id);
        model.addAttribute("user",user);
        model.addAttribute("title","查看用户");
        return new ModelAndView("users/view","userModel",model);
    }

    /**
     * 获取创建表单页面
     * @param model
     * @return
     */
    @GetMapping("/form")
    public ModelAndView createForm(Model model){
        model.addAttribute("user",new User());
        model.addAttribute("title","创建用户");
        return new ModelAndView("users/form","userModel",model);
    }

    /**
     * 更新用户
     * @param user
     * @return
     */
    @PostMapping
    public ModelAndView saveOrUpdateUser(User user){
        user=userRepository.saveOrUpdateUser(user);
        return new ModelAndView("redirect:/users");
    }

    /**
     * 根据id删除用户
     * @param id
     * @return
     */
    @GetMapping("/delete/{id}")
    public ModelAndView delete(@PathVariable("id")Long id){
        userRepository.deleteUser(id);
        return new ModelAndView("redirect:/users");
    }

    /**
     * 根据id修改用户
     * @param id
     * @param model
     * @return
     */
    @GetMapping("/modify/{id}")
    public ModelAndView modify(@PathVariable("id")Long id,Model model){
        User user=userRepository.getUserById(id);
        model.addAttribute("user",user);
        model.addAttribute("title","修改用户");
        return new ModelAndView("users/form","userModel",model);
    }

}
  • header.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
    <meta charset="UTF-8">
    <title>Thymeleaf in action</title>
</head>
<body>
    <div th:fragment="header">
        <h1>Thymeleaf in action</h1>
        <a href="/users" th:href="@{~/users}">首页</a>
    </div>
</body>
</html>
  • footer.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
    <meta charset="UTF-8">
    <title>Thymeleaf in action</title>
</head>
<body>
    <div th:fragment="footer">
        <a href="https://waylau.com">Welcom to waylau.com</a>
    </div>

</body>
</html>
  • list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
    <meta charset="UTF-8">
    <title>Thymeleaf in action</title>
</head>
<body>
<!--头部信息引入-->
<div th:replace="~{fragments/header :: header }"></div>
<h3 th:text="${userModel.title}"></h3>
<div>
    <a href="/users/form.html" th:href="@{/users/form}">创建用户</a>
</div>
<table border="1">
    <thead >
     <tr>
         <td>ID</td>
         <td>Email</td>
         <td>Name</td>
     </tr>
    </thead>
    <tbody>
      <tr th:if="${userModel.userList.size()} eq 0">
            <td colspan="3">没有用户信息!</td>
      </tr>
      <tr th:each="user : ${userModel.userList}">
          <td th:text="${user.id}"></td>
          <td th:text="${user.email}"></td>
          <td><a th:href="@{'/users/'+${user.id}}"  th:text="${user.name}"></a></td>
      </tr>
    </tbody>
</table>
<!--尾部信息引入-->
<div th:replace="~{fragments/footer :: footer }"></div>
</body>
</html>
  • form.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
    <meta charset="UTF-8">
    <title>Thymeleaf in action</title>
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<h3 th:text="${userModel.title}">waylau</h3>
<form action="/users" th:action="@{/users}" method="POST" th:object="${userModel.user}">
   <input type="hidden" name="id" th:value="*{id}">
    名称:<br/><input type="text" name="name" th:value="*{name}"><br/>
    邮箱:<br/><input type="text" name="email" th:value="*{email}">
    <input type="submit" value="提交">
</form>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>
  • view.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
    <meta charset="UTF-8">
    <title>Thymeleaf in action</title>
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<h3 th:text="${userModel.title}">waylau</h3>
<div>
    <p><strong>ID:</strong><span th:text="${userModel.user.id}"></span></p>
    <p><strong>Name:</strong><span th:text="${userModel.user.name}"></span></p>
    <p><strong>Email:</strong><span th:text="${userModel.user.email}"></span></p>
</div>
<div>
    <a th:href="@{'/users/delete/'+${userModel.user.id}}">删除</a>
    <a th:href="@{'/users/modify/'+${userModel.user.id}}">修改</a>
</div>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/qq_31247177/article/details/80623754