前言
公司 App 后台我是使用 Asp.Net Mvc 5 开发的,公司整体技术已经转向 Java,所以我也准备学一学入门一下。我用了一周的时间使用 Spring Boot 将后台迁移到 Java。现将此过程学到的记录下来,有些术语是使用微软那一套去理解的,不要纠结。
@RequestMapping 路由映射
Url 映射
RequestMapping 注解是用来映射 Url 的。可以放在类上,也可以放在方法上。为类映射:
@RequestMapping("api/app")
public class AppController { }
这样就将 api/app 映射到 AppController 类。方法的映射也是一样:
@RequestMapping("appIsAudit")
public Map appIsAudit() {
// 实现代码
}
如果类上添加了 Url 映射,类中的方法会继承类的 Url,上面的 appIsAudit 方法如果在 AppController 类中,那么路径为:api/app/appIsAudit。
多个 Url 映射
@RequestMapping({"/", "default", "index"})
这样就将 /、/default、/index 映射到同一个方法中。
RESTful
@RequestMapping("index/{userId}")
public String index(Model model, @PathVariable String userId) {
// 实现代码
}
指定 HTPP 方法
@RequestMapping(value = "autoSaveTest", method = RequestMethod.POST)
指定多个 HTPP 方法
@RequestMapping(value = "autoSaveTest", method = {RequestMethod.POST, RequestMethod.GET})
忽略大小写
RequestMapping 路径是大小写敏感的,@RequestMapping(“appIsAudit”) 使用 appIsAudit 是可以请求到,但是使用 Appisaudit 是请求不到的。忽略大小写:
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
AntPathMatcher matcher = new AntPathMatcher();
matcher.setCaseSensitive(false);
configurer.setPathMatcher(matcher);
}
}
Api接口
在类上添加 @RestController 注解即可
@RestController
@RequestMapping("api/app")
public class AppController { }
页面
在类上添加 @Controller 注解即可
@Controller
public class HomeController { }
thymeleaf
Thymeleaf 提供了一个用于整合 Spring MVC 的可选模块,在应用开发中,你可以使用 Thymeleaf 来完全代替 JSP,或其他模板引擎,如 Velocity、FreeMarker 等。Thymeleaf 的主要目标在于提供一种可被浏览器正确显示的、格式良好的模板创建方式,因此也可以用作静态建模。你可以使用它创建经过验证的 XML 与 HTML 模板。相对于编写逻辑或代码,开发者只需将标签属性添加到模板中即可。接下来,这些标签属性就会在 DOM(文档对象模型)上执行预先制定好的逻辑。
使用 thymeleaf
pom.xml 文件 dependencies 添加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
页面存放路径
src/main/resources/templates/
使用页面
在 templates 文件夹创建 .html 文件,在 @Controller 中返回对应的 .html 文件名即可。
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>首页</title>
</head>
<body>
首页
</body>
</html>
HomeController.java
@Controller
public class HomeController {
@RequestMapping({"/","index"})
public String index() {
return "index";
}
}
这样 HomeController 中的 index 方法就会和 index.html 绑定了。
使用布局
在开发中,很多页面的布局都是统一的,不一样的只是内容。例如网站的导航就是统一的。一般会把这些一致的部分提取出来做成公共的,使用时只需要引入布局界面。
布局页中使用 layout:fragment 定义,作为需要改变的内容区域,下面是布局页 layout.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<link rel="apple-touch-icon" sizes="57x57" href="/images/apple-touch-icon-114.png"/>
<link rel="apple-touch-icon" sizes="114x114" href="/images/apple-touch-icon-114.png"/>
<link rel="apple-touch-icon" sizes="72x72" href="/images/apple-touch-icon-144.png"/>
<link rel="apple-touch-icon" sizes="144x144" href="/images/apple-touch-icon-144.png"/>
<link rel="icon" type="image/x-icon" href="/images/favicon.ico"/>
<link rel="stylesheet" href="/bootstrap-3.3.7/css/bootstrap.min.css"/>
<script src="/jquery-3.1.1.min.js"></script>
<script src="/bootstrap-3.3.7/js/bootstrap.min.js"></script>
<script src="/layer_mobile/layer.js"></script>
</head>
<body>
<div class="container" style="margin-top: 15px;">
<!--定义改变等内容-->
<div layout:fragment="content"></div>
</div>
</body>
</html>
引用布局页面使用 layout:decorator 定义,下面是 index.html 使用布局页
<!--引用 layout 布局页-->
<html layout:decorator="layout">
<head>
<title>title</title>
</head>
<div layout:fragment="content">
<ul class="list-group">
<li class="list-group-item" style="text-align:center;"><span class="glyphicon glyphicon-info-sign"></span>
yiboshi App for java v1.0
</li>
</ul>
</div>
</html>
此时 index.html 会合并内容,完整内容为
<!DOCTYPE html>
<html>
<head>
<title>title</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<link rel="apple-touch-icon" sizes="57x57" href="/images/apple-touch-icon-114.png"/>
<link rel="apple-touch-icon" sizes="114x114" href="/images/apple-touch-icon-114.png"/>
<link rel="apple-touch-icon" sizes="72x72" href="/images/apple-touch-icon-144.png"/>
<link rel="apple-touch-icon" sizes="144x144" href="/images/apple-touch-icon-144.png"/>
<link rel="icon" type="image/x-icon" href="/images/favicon.ico"/>
<link rel="stylesheet" href="/bootstrap-3.3.7/css/bootstrap.min.css"/>
<script src="/jquery-3.1.1.min.js"></script>
<script src="/bootstrap-3.3.7/js/bootstrap.min.js"></script>
<script src="/layer_mobile/layer.js"></script>
</head>
<body>
<div class="container" style="margin-top: 15px;">
<div>
<ul class="list-group">
<li class="list-group-item" style="text-align:center;"><span class="glyphicon glyphicon-info-sign"></span>
yiboshi App for java v1.0
</li>
</ul>
</div>
</div>
</body>
</html>
使用部件(代码片段)
部件页中使用 th:fragment 定义,下面是部件页 wxPart.html。 这段代码主要作用为在微信中隐藏微信菜单栏
<script th:fragment="wxHideMenu">
function onBridgeReady() {
WeixinJSBridge.call('hideOptionMenu');
}
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
} else {
onBridgeReady();
}
</script>
引用部件页面使用 th:include 定义,下面是 index.html 使用部件页
<html layout:decorator="layout">
<head>
<title>title</title>
<script th:include="wxPart :: wxHideMenu"></script>
</head>
<div layout:fragment="content">
<ul class="list-group">
<li class="list-group-item" style="text-align:center;"><span class="glyphicon glyphicon-info-sign"></span>
yiboshi App for java v1.0
</li>
</ul>
</div>
</html>
此时 index.html 会合并内容,完整内容为
<!DOCTYPE html>
<html>
<head>
<title>title</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<link rel="apple-touch-icon" sizes="57x57" href="/images/apple-touch-icon-114.png"/>
<link rel="apple-touch-icon" sizes="114x114" href="/images/apple-touch-icon-114.png"/>
<link rel="apple-touch-icon" sizes="72x72" href="/images/apple-touch-icon-144.png"/>
<link rel="apple-touch-icon" sizes="144x144" href="/images/apple-touch-icon-144.png"/>
<link rel="icon" type="image/x-icon" href="/images/favicon.ico"/>
<link rel="stylesheet" href="/bootstrap-3.3.7/css/bootstrap.min.css"/>
<script src="/jquery-3.1.1.min.js"></script>
<script src="/bootstrap-3.3.7/js/bootstrap.min.js"></script>
<script src="/layer_mobile/layer.js"></script>
<script th:fragment="wxHideMenu">
function onBridgeReady() {
WeixinJSBridge.call('hideOptionMenu');
}
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
} else {
onBridgeReady();
}
</script>
</head>
<body>
<div class="container" style="margin-top: 15px;">
<div>
<ul class="list-group">
<li class="list-group-item" style="text-align:center;"><span class="glyphicon glyphicon-info-sign"></span>
yiboshi App for java v1.0
</li>
</ul>
</div>
</div>
</body>
</html>
变量绑定
后台和前台使用变量进行传值,后台使用 Model.addAttribute 方法添加变量,前台使用 ${变量} 表达式读取值。
后台方法
@RequestMapping({"/","Index"})
public String Index(Model model) {
model.addAttribute("Msg", "yiboshi App for java v1.0");
return "Index";
}
.html
<!--读取 Msg 值-->
<span th:text="${Msg}"></span>
JavaScript 变量绑定
如果在 JavaScript 中读取变量首先需要在 script 标签中添加 th:inline=”javascript”。然后需要使用 /*<![CDATA[*/JavaScript 代码/*]]>*/ 包裹 JavaScript 代码。读取变量值使用 /*[[${变量}]]*/
<script th:inline="javascript">
/*<![CDATA[*/
var msg = /*[[${Msg}]]*/ "";
/*]]>*/
</script>