9.Spring Boot 与 Web 开发
1.使用SpringBoot
1.创建Spring Boot 应用,选中我们需要的模块
2.Spring Boot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来
3.自己编写业务逻辑
2.SpringBoot对静态资源的映射规则
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
}
-
所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 寻找资源;
webjars: 以jar包的形式引入静态资源;
比如在 webjar 网站(https://www.webjars.org/)中以 maven 形式将依赖复杂到pom中即可;
用
<dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.4.1</version> </dependency>
导入jquery依赖后
可见目录结构满足搜索条件
[外链图片转存失败(img-hVjegjbh-1569155395673)(C:\Users\Y\Desktop\杂\1568463607996.png)]
输入 http://localhost:8080/webjars/jquery/3.4.1/jquery.js 可访问到该 js 文件
-
“/**” 访问当前路径的任何资源,(静态资源文件夹)
classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/ ("/":当前项目的根路径)
localhost:8080/abc ===> 去静态资源文件夹里去找abc
-
配置欢迎页( “localhost:8080/” )映射
静态资源文件夹下所有的 index.html 页面;被 “/**” 映射;
-
配置图标
所有的 “**/favicon.ico” 都是在静态资源文件夹下找
-
静态资源文件夹可以自己设置
pom中的 spring.resource.static-locations
3.模板引擎
Jsp , Velocity , Freemarker , Thymeleaf ;
[外链图片转存失败(img-80iMbKRP-1569155395674)(C:\Users\Y\Desktop\杂\1568466648360.png)]
SpringBoot推荐的 Thymeleaf ;
语法更简单,功能更强大 ;
用来取代 jsp
1.引入 Thymeleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
版本控制:
<properties>
<thymeleaf.version>3.0.0.RELEASE</thymeleaf.version>
<!-- 布局功能的支持程序 thymeleaf3主程序 layout2以上版本 -->
<thymeleaf-layout-dialect.version>2.0.0</thymeleaf-layout-dialect.version>
</properties>
可以在 github 上搜索 thymeleaf 和 thymeleaf-layout-dialect 去查看版本
2.Thymeleaf的使用和语法
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
只要我们把 html 页面放在 classpath:/templates/ ,thymeleaf就能自动渲染
1.导入 thymeleaf 的名称空间
<html lang="en" xmlns:th="http://www.thymeleaf.org">
2.使用 thymeleaf 语法
使用实例
controller层
@Controller
public class HelloController {
@RequestMapping("hello1")
public String hello(Map<String,Object> map){
map.put("content1","thymeleaf content");
return "hello";
}
}
html页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>这是hello</h1>
<h2 th:text="content1">default content</h2>
</body>
</html>
th:任意html属性 :来替换原生属性的值
[外链图片转存失败(img-twVZYqsW-1569155395675)(C:\Users\Y\AppData\Roaming\Typora\typora-user-images\1568618843552.png)]
表达式:
${…} 获取变量值(获取对象的属性,调用方法);
${#…} 获取内置对象
*{…} 和 . . . 类 似 , 有 一 些 补 充 功 能 , 配 合 t h : o b j e c t = " {...}类似,有一些补充功能,配合 th:object=" ...类似,有一些补充功能,配合th:object="{session.user}" 使用
举例:
[外链图片转存失败(img-oyRdoiZi-1569155395676)(C:\Users\Y\AppData\Roaming\Typora\typora-user-images\1568619460828.png)]
#{…} 获取国际化内容
@{url} 定义url
举例:
@{/order/process(execId=${execId},execType='FAST')}
~{…} 片段引用表达式
需要注意的地方:使用thymeleaf的时候 ,Controller 层 不要加 @ResponseBody ,否则会在页面显示字符串而不是该html页面
4.扩展SpringMVC
编写一个配置类(@Configuration),是WebMvcConfigurerAdapter类型,不能标注@EnableWebMvc(全面接管SpringMVC);(现在已经过时,只需要直接实现 WebMvcConfigurer 接口即可)
举例
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/viewcontroller1").setViewName("hello");
}
}
浏览器发送 /viewcontroller1 请求来到 hello 页面;
这样做的好处是:实现的跳转效果就像 @RequestMapping 一样,但是不需要再写空方法了;
5.RestfulCRUD
1.默认访问首页
第一种方法,把 index 放在 templates 中让 thymeleaf 进行解析并在 Controller 中添加视图映射
@RequestMapping("/")
public String index(){
return "index";
}
第二种方法,在 MVC 组件中添加视图映射
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/viewcontroller1").setViewName("hello");
registry.addViewController("/").setViewName("index");
registry.addViewController("/111").setViewName("index");
}
}
2.登陆
例子:
<form th:action="@{/user/login}" method="post">
<!-- 检查是否登陆成功 -->
<p style="color:red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
<p>username:<input type="text" name="username"></p>
<p>password:<input type="password" name="password"></p>
<input type="submit" value="login">
</form>
@Controller
public class LoginController {
@PostMapping(value = "/user/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Map<String,Object> map){
if (!StringUtils.isEmpty(username) && "123".equals(password)){
return "redirect:/loginsuccess";
}else {
map.put("msg","用户名或密码错误");
return "login";
}
}
}
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/loginsuccess").setViewName("loginsuccess");
}
}
需要注意的地方:我没有在controller中直接进行登陆成功的跳转,因为这样的话会导致刷新后表单重复提交(css等无法加载?)等问题,所以改为更改视图映射和controller,使得网页重定向跳到登陆成功页面;
但是这样会导致一个问题:将登陆成功页在其他浏览器打开,也能进去,因为没有进行判断,所以我们下面要进行登陆检查;
3.拦截器进行登陆检查
在登陆成功时在 session 中添加信息,然后在拦截器中进行检查
如下:
修改一下,添加session
@PostMapping(value = "/user/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Map<String,Object> map,
HttpSession session){
if (!StringUtils.isEmpty(username) && "123".equals(password)){
session.setAttribute("loginedUsername",username);
return "redirect:/loginsuccess";
}else {
map.put("msg","用户名或密码错误");
return "login";
}
}
创建拦截器
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object user = request.getSession().getAttribute("loginedUsername");
if(user == null){
//登陆失败
request.setAttribute("msg","没有权限,请先登陆");
request.getRequestDispatcher("/").forward(request,response);
return false;
}else{
return true;
}
}
}
在mvcConfig中添加拦截器
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/","/user/login");
}
其中 addPathPatterns("/**") 指对所有url进行拦截 ,excludePathPatterns("/","/user/login") 指除了这几个url ,否则连最基础的登陆都被拦截下来了;
4.CRUD 员工列表
实验要求:
-
RestfulCRUD:CRUD 满足 Restful 风格;
URI: /资源名称/资源标识 HTTP请求方式区分对资源CRUD操作
普通 CRUD(uri来区分操作) RestfulCRUD 查询 getEmp emp—Get 添加 addEmp?xxx emp—POST 修改 updateEmp?id=xx&xx=xx emp/{id}—PUT 删除 deleteEmp?id=xx emp/{id}—DELETE -
实验的请求架构
请求uri 请求方式 查询所有员工 emps GET 查询某个员工(来到修改页面) emp/{id} GET 来到添加页面 emp GET 添加员工 emp POST 来到修改页面(查出员工进行信息回显) emp/{id} GET 修改员工 emp PUT 删除员工 mep/{id} DELETE -
员工列表
重复的界面:关于 thymeleaf 的代码重用(th:fragment ,th:insert …),略;
使用 th:each 来添加数据;
SpringMVC 自动将请求参数与入参对象的属性进行一一绑定;要求请求参数的名字和javaBean入参的对象里面的属性名一致;
这样就不用写中间代码了;
举例:
<form th:action="@{/emp}" method="post"> <p>name:<input type="text" name="name"></p> <p>age:<input type="text" name="age"></p> <p><input type="submit" value="add"></p> </form>
@PostMapping(value = "/emp") public String addEmployee(Employee employee){ System.out.println(employee); return "redirect:/list"; }
输入 name 为 yy ; age 为 11
Console:
Employee(name=yy, age=11)
5.发送PUT等请求
1.SpringMVC中配置HiddenHttpMethodFilter;(SpringBoot自动配置好的)
2.页面创建一个 post 表单
3.创建一个 input 项,name = “_method” ; 值就是我们请求的方式;
<input type="hidden" name="_method" value="put"/>