Spring Web全栈

依赖注入(DI)是 Spring 最核心的技术点

- Maven
Maven 是一个项目管理和构建自动化工具
在这里插入图片描述
在这里插入图片描述

Maven 使用惯例优于配置的原则 。它要求在没有定制之前,所有的项目都有如下的结构:
在这里插入图片描述
这里的 ${basedir} 代表的是 Java 工程的根路径,在我们这里就是工程的根目录啦。一个 Maven 项目在默认情况下会产生 JAR (Java 的一种压缩格式)文件,另外 ,编译后 的 classes 会放在 ${basedir}/target/classes 下面, JAR 文件会放在 ${basedir}/target 下面

- Maven命令
1、mvn clean compile
编译命令,Maven 会自动扫描 src/main/java 下的代码并完成编译工作,执行完,会在根目录下生成 target/classes 目录(存放所有的 class)
2、mvn clean package
编译并打包命令,这个命令是 compile 和 package 的集合,也就是说会先执行 compile 命令,然后在执行 jar 打包命令,这个的结果会把所有的 java 文件和资源打包成一个jar,jar 是 java 的一个压缩格式,方便我们灵活的运用多个代码
3、mvn clean install
执行安装命令,这个命令是 compile 和 package、install 的集合,也就是说会先执行 compile 命令,然后在执行 jar 打包命令,然后执行 install 命令安装到本地的 Maven 仓库目录里,这个目录是${user_home}/.m2
这个 ${user_home} 指的就是你的电脑登录用户名的个人目录
4、mvn compile exec:java -Dexec.mainClass=${main}
这个命令的意思是在 compile 执行完后,执行运行 Java 的命令,具体执行哪个 Java 类是由 -Dexec.mainClass=${main} 参数指定的,比如hello我们想执行 com.hello.Test类,那么这个完整的命令就是
mvn compile exec:java -Dexec.mainClass=com.hello.Test
- Maven配置
pom.xml(Project Object Model)
在这里插入图片描述
在这里插入图片描述
一般我们会把别人写的代码库称为三方库,自己、团队写的称为二方库;
阿里云镜像服务器 https://maven.aliyun.com/mvn/search

- Annotation (注解)
在这里插入图片描述

1、Target
java.lang.annotation.Target自身也是一个注解,它只有一个数组属性,用于设定该注解的目标范围,比如说可以作用于类或者方法等。因为是数组,所以可以同时设定多个范围
在这里插入图片描述
2、Retention
在这里插入图片描述
3、Documented
在这里插入图片描述
4、@interface
在这里插入图片描述

5、Annotation 属性


- Spring Bean
IoC(Inversion of Control,控制反转) 容器是 Spring 框架最最核心的组件,没有 IoC 容器就没有 Spring 框架。

房屋中介         IoC

1. 找中介     ----> 1. 找IoC容器

2. 中介介绍房子  ----> 2. 找IoC容器

3. 租房、入住   ----> 3. 使用对象

Spring 主要有两种配置元数据的方式,一种是基于 XML、一种是基于 Annotation 方案的,目前主流的方案是基于 Annotation 的,Annotation 类型的 IoC 容器对应的类是

org.springframework.context.annotation.AnnotationConfigApplicationContext

如果要启动 IoC 容器,可以运行下面的代码

ApplicationContext context = 
    new AnnotationConfigApplicationContext("fm.douban");

在这里插入图片描述

- 自动注入(Autowired)
前提当前类是SpringBean

- Spring Rosource
在 Spring 当中定义了一个 org.springframework.core.io.Resource 类来封装文件,这个类的优势在于可以支持普通的 File 也可以支持 classpath 文件。

//创建接口
public interface FileService {

    String getContent(String name);

}
//实现类
import fm.douban.service.FileService;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;

@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private ResourceLoader loader;

    @Override
    public String getContent(String name) {
        try {
            InputStream in = loader.getResource(name).getInputStream();
            return IOUtils.toString(in,"utf-8");
        } catch (IOException e) {
           return null;
        }
    }
}
 //调用
 FileService fileService = context.getBean(FileService.class);
  //读取resources目录下文件
  String content = fileService.getContent("classpath:data/urls.txt");
  System.out.println(content);
//读取工程目录下文件
 String content2 = fileService.getContent("file:mywork/readme.md");
        System.out.println(content2);
//抓取网站
String content2 = fileService.getContent("https://www.zhihu.com/question/34786516/answer/822686390");
System.out.println(content2);

- SpringBean的生命周期(Lifecycle)
在这里插入图片描述
通过添加注释@PostConstruct声明方法init,就可以使该方法在 Spring Bean 启动后会自动执行


- SpringMVC

  • SpringController
    基本上所有的网页加载都是这样的一个过程。在 Spring Boot 方案里,一个网页请求到了服务器后,首先我们进入的是 Java Web 服务器,然后进入到 Spring Boot 应用,最后匹配到某一个 Spring Controller (这其实也是一个 Spring Bean),然后路由到具体某一个 Bean 的方法,执行完后返回结果,输出到客户端来。
    在这里插入图片描述
  • RequestMapping注解
    完成路由配置
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloControl {

    @RequestMapping("/hello")
    public String say(){
        return "html/hello.html";
    }

}
  • Get Request
    获取 Http URL 参数: 用@RequestParam注解
 public String index( @RequestParam("id") String id)
 public String index(@RequestParam("id") String id,  @RequestParam("pageNum") int pageNum)

@ResponseBody注解Spring MVC 会自动的把对象转化成 JSON 字符串输出到网页了,这也是 Spring MVC 比较强大和方便的地方,一般我们会把这种输出JSON数据的方法称为 API


- Thymeleaf
Thymeleaf 是一个模板框架,它可以支持多种格式的内容动态渲染非常强大,它天然和 HTML 是相融合的,Thymeleaf 模板文件也是以 html 作为文件格式的
Spring MVC 把页面数据层封装的非常完善,只需要我们在方法参数里引入一个Model对象,就可以通过这个 Model 对象传递数据到页面中了。

 @Controller
public class SongListControl {

  @Autowired
  private SongListService songListService;

  @RequestMapping("/songlist")
  public String index(@RequestParam("id")String id,Model model){

    SongList songList = songListService.get(id);
    //传递歌单对象到模板当中
    //第一个 songList 是模板中使用的变量名
    // 第二个 songList 是当前的对象实例
    model.addAttribute("songList",songList);//添加到模板上下文

    return "songList";
  }
}
  • Thymeleaf变量
<span th:text="${msg}">Hello</span>

这段代码的执行结果就是用 msg 变量值替换了 span 标签内的 Hello 字符串,比如说 msg 变量值是你好,那么代码渲染的结果是

<span>你好</span>
  • Thymeleaf循环
    th:each 代表的就是循环语句
<ul th:each="song : ${songs}">
  <li th:text="${song.name}">歌曲名称</li>
</ul>

在这里插入图片描述

<ul th:each="song,it: ${songs}">
  <li>
    <span th:text="${it.count}"></span>
    <span th:text="${song.name}"></span>
  </li>
</ul>

在这里插入图片描述

- Thymeleaf表达式
Thymeleaf 表达式主要用于两种场景:
1、字符串处理

  • 字符串拼接:<span th:text="'00:00/'+${totalTime}"></span>
  • 字符串拼接优化:<span th:text="|00:00/${totalTime}|"></span>

2、数据转化

  • Thymeleaf 默认集成了大量的工具类可以方便的进行数据转化,一般我们使用最多的是dates
    工具类的运用和变量不同,变量使用的是 ${变量名},工具类使用的是#{工具类}
<p th:text="${#dates.format(dateVar, 'yyyy-MM-dd HH:mm:ss')}"></p>
<p th:text="${#dates.format(dateVar, 'yyyy年MM月dd日 HH时mm分ss秒')}"></p>

dates 和 temporals 支持的方法是一样的,只是支持的类型不同,dates 支持的是 Date 类,temporals 支持的是 LocalDate 和 LocalDateTime

  • 除了日期方法,#strings 也是我们使用比较多的,支持字符串的数据处理,比如
    在这里插入图片描述
  • 内联表达式
    尽管我们使用 th:text 也比较方便,但是有些时候可能我们还是更喜欢直接把变量写在 HTML 中,比如这种写法
<span>Hello [[${msg}]]</span>//结果中有Hello

上面的[[变量]]这种格式就是内联表达式,支持我们直接在 HTML 中调用变量

[[]] 是用来替代 th:text 的,不是替代所有的th:标签哦


  • Thymeleaf条件语句
    1、以th:开头的属性,这次我们使用的是 th:if,if 表达式的值是 ture 的情况下就会执行渲染<span th:if="${user.sex == 'male'}">男</span>
    2、还可以使用 th:unless 代表的是否定条件,这个语句和 if 是相反的,表达式的值是 false 情况才会执行渲染
    3、th:if 条件判断除了判断 boolean 值外,Thymeleaf 还认为如下表达式为 true:
    在这里插入图片描述
  • #strings.contains
    检查字符串变量是否包含片段
${#strings.contains(name,'abc')}
  • strings 逻辑判断
    在这里插入图片描述
    在这里插入图片描述

  • Spring Validation
    Spring 对于数据验证支持的也非常好,我们可以借助 Spring Validation 来处理表单数据的验证

  • Validation 注解
    在这里插入图片描述
    大多数情况下,我们建议使用 NotEmpty 替代 NotNull、NotBlank

举例:

package com.bookstore.model;

import javax.validation.constraints.*;

public class User {

    @NotEmpty(message = "名称不能为 null")
    private String name;

    @Min(value = 18, message = "你的年龄必须大于等于18岁")
    @Max(value = 150, message = "你的年龄必须小于等于150岁")
    private int age;

    @NotEmpty(message = "邮箱必须输入")
    @Email(message = "邮箱不正确")
    private String email;

    // standard setters and getters 
}

- SpringBoot
报错

Field subjectService in fm.douban.app.control.SongListControl required a bean of type 'fm.douban.service.SubjectService' that could not be found.

在这里插入图片描述
在这里插入图片描述

@SpringBootApplication(scanBasePackages={"fm.douban.app", "fm.douban.service"})
public class AppApplication {
  public static void main(String[] args) {
    SpringApplication.run(AppApplication.class, args);
  }
}

在这里插入图片描述

  • Spring Boot Logger的应用
    在这里插入图片描述
    配置中可设置日志级别,如
logging.level.fm.douban.app=info

在这里插入图片描述
在这里插入图片描述

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;

@RestController
public class SongListControl {
    private static final Logger LOG = LoggerFactory.getLogger(SongListControl.class);

    @PostConstruct
    public void init(){
        LOG.info("SongListControl 启动啦");
    }
}
  • 配置文件application.properties
    通过@Value注解读取配置内容,例如:
song.name=God is a girl
import org.springframework.beans.factory.annotation.Value;

public class SongListControl {
    @Value("${song.name}")
    private String songName;
}

只需要使用 @Value 注解即可,注意写法,花括号中的配置项名称,与配置文件中保持一致即可。


- Spring Session

  • 读Cookie
    在这里插入图片描述
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

@RequestMapping("/songlist")
public Map index(HttpServletRequest request) {
  Map returnData = new HashMap();
  returnData.put("result", "this is song list");
  returnData.put("author", songAuthor);

  Cookie[] cookies = request.getCookies();
  returnData.put("cookies", cookies);

  return returnData;
}
  • 写Cookie
    在这里插入图片描述
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

@RequestMapping("/songlist")
public Map index(HttpServletResponse response) {
  Map returnData = new HashMap();
  returnData.put("result", "this is song list");
  returnData.put("name", songName);

  Cookie cookie = new Cookie("sessionId","CookieTestInfo");
  // 设置的是 cookie 的域名,就是会在哪个域名下生成 cookie 值
  cookie.setDomain("baidu.com");
  // 是 cookie 的路径,一般就是写到 / ,不会写其他路径的
  cookie.setPath("/");
  // 设置cookie 的最大存活时间,-1 代表随浏览器的有效期,也就是浏览器关闭掉,这个 cookie 就失效了。
  cookie.setMaxAge(-1);
  // 设置是否只能服务器修改,浏览器端不能修改,安全有保障
  cookie.setHttpOnly(false);
  response.addCookie(cookie);

  returnData.put("message", "add cookie successfule");
  return returnData;
}

Cookie重要属性

  • Session
    Cookie放在客户端,Session放在服务器端,相比之下信息会更安全
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 读操作
    在这里插入图片描述
    登录信息类

import java.io.Serializable;

public class UserLoginInfo implements Serializable {
  private String userId;
  private String userName;
}
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@RequestMapping("/songlist")
public Map index(HttpServletRequest request, HttpServletResponse response) {
  Map returnData = new HashMap();
  returnData.put("result", "this is song list");

  // 取得 HttpSession 对象
  HttpSession session = request.getSession();
  // 读取登录信息
  UserLoginInfo userLoginInfo = (UserLoginInfo)session.getAttribute("userLoginInfo");
  if (userLoginInfo == null) {
    // 未登录
    returnData.put("loginInfo", "not login");
  } else {
    // 已登录
    returnData.put("loginInfo", "already login");
  }

  return returnData;
}
  • 写操作
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@RequestMapping("/loginmock")
public Map loginMock(HttpServletRequest request, HttpServletResponse response) {
  Map returnData = new HashMap();

  // 假设对比用户名和密码成功
  // 仅演示的登录信息对象
  UserLoginInfo userLoginInfo = new UserLoginInfo();
  userLoginInfo.setUserId("12334445576788");
  userLoginInfo.setUserName("ZhangSan");
  // 取得 HttpSession 对象
  HttpSession session = request.getSession();
  // 写入登录信息
  session.setAttribute("userLoginInfo", userLoginInfo);
  returnData.put("message", "login successfule");

  return returnData;
}
  • SpringRequest 拦截器
    Spring提供的一种统一处理相同逻辑的机制
    实现拦截器有三个步骤:
    1、创建拦截器
    在这里插入图片描述
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class InterceptorDemo implements HandlerInterceptor {

  // Controller方法执行之前
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    // 只有返回true才会继续向下执行,返回false取消当前请求
    return true;
  }

  //Controller方法执行之后
  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
      ModelAndView modelAndView) throws Exception {

  }

  // 整个请求完成后(包括Thymeleaf渲染完毕)
  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

  }
}

2、实现 WebMvcConfigurer
在这里插入图片描述

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebAppConfigurerDemo implements WebMvcConfigurer {

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    // 多个拦截器组成一个拦截器链
    // 仅演示,设置所有 url 都拦截
    registry.addInterceptor(new UserInterceptor()).addPathPatterns("/**");
  }
}

通常拦截器,会放在一个包(例如interceptor)里。而用于管理拦截器的配置类,会放在另一个包(例如config)里。

  • 页面跳转
    在这里插入图片描述

- MongoDB数据库
对数据库的操作一定要放在 @Service 类中,而不是放在 @Controller 类中;且 @Controller 类可以调用 @Service 类的方法,反之则不行。这是 SpringMVC 的经典架构设计理念

import org.springframework.data.mongodb.core.MongoTemplate;

  @Autowired
  private MongoTemplate mongoTemplate;

  public void test() {
    Song song = new Song();
    song.setSubjectId("s001");
    song.setLyrics("...");
    song.setName("成都");

    mongoTemplate.insert(song);
  }
mongoTemplate.findById(songId, Song.class)
// 修改 id=1 的数据
Query query = new Query(Criteria.where("id").is("1"));

// 把歌名修改为 “new name”
Update updateData = new Update();
updateData.set("name", "new name");

// 执行修改,修改返回结果的是一个对象
UpdateResult result = mongoTemplate.updateFirst(query, updateData, Song.class);
// 修改的记录数大于 0 ,表示修改成功
System.out.println("修改的数据记录数量:" + result.getModifiedCount());

在这里插入图片描述

Song song = new Song();
song.setId(songId);

// 执行删除
DeleteResult result = mongoTemplate.remove(song);
// 删除的记录数大于 0 ,表示删除成功
System.out.println("删除的数据记录数量:" + result.getDeletedCount());
  • 条件查找
    在这里插入图片描述
// 条件对象构建查询对象
    Query query = new Query(criteria);
 
    List<Song> songs = mongoTemplate.find(query, Song.class);

    return songs;
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值