11111111111111111111111111

🍅 作者简介:哪吒,CSDN2021博客之星亚军🏆、新星计划导师✌、博客专家💪

🍅 哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师

🍅 关注公众号【哪吒编程】,回复1024,获取Java学习路线思维导图、大厂面试真题、加入万粉计划交流群、一起学习进步

目录

一、开发web应用

二、json接口开发

1、 添加jackjson等相关的jar包

2、配置spring controller扫描包

3、对接的方法添加 @ResponseBody

三、自定义filter

1、实现filter接口,实现filter方法

2、添加 @Configuration 注解,将自定义filter加入过滤链

四、自定义property

1、配置在application.properties中

2、自定义配置类

3、log配置

五、数据库操作

1、添加相关jar包

2、添加配置文件

3、添加实体类和dao

4、测试

六、Thymeleaf 模板

1、Thymeleaf介绍

2、页面即原型

七、Gradle构建工具

八、 WebJars

1、什么是 WebJars

2、为什么使用

3、如何使用

九、CRUD

1、先看一下项目架构

2、扩展SpringMVC的功能

3、controller

4、前端页面

5、实现效果


一、开发web应用

Spring Boot Web 开发非常的简单,其中包括常用的 json 输出、filters、property、log 等

二、json接口开发

以前使用spring开发项目,需要提供json接口时需要做什么呢?

1、 添加jackjson等相关的jar包

2、配置spring controller扫描包

3、对接的方法添加 @ResponseBody

我们经常由于配置错误出现406错误,由于扫描包理解不到位的配置错误(SSM框架就遇到了,搞了好几天才解决掉!)等等,springboot如何做呢,只需要类添加 @RestController  即可,默认类中的方法都会以json的格式返回


    
    
  1. @RestController
  2. public class HelloController {
  3. @RequestMapping( "/getUser")
  4. public User getUser( ) {
  5. User user= new User();
  6. user. setUserName( "素小暖");
  7. user. setPassWord( "xxxx");
  8. return user;
  9. }
  10. }

如果需要使用页面开发只要使用@Controller注解即可,下面会结合模板来说明。

三、自定义filter

我们常常在项目中会使用filters用于调用日志、排除有XXS威胁的字符、执行权限验证等等。

springboot自动添加了 OrderedCharacterEncodingFilter 和 HiddenHttpMethodFilter, 并且我们可以自定义filter。

两个步骤

1、实现filter接口,实现filter方法

2、添加 @Configuration 注解,将自定义filter加入过滤链


    
    
  1. @Configuration
  2. public class WebConfiguration {
  3. @Bean
  4. public RemoteIpFilter remoteIpFilter () {
  5. return new RemoteIpFilter();
  6. }
  7. @Bean
  8. public FilterRegistrationBean testFilterRegistration () {
  9. FilterRegistrationBean registration = new FilterRegistrationBean();
  10. registration.setFilter( new MyFilter());
  11. registration.addUrlPatterns( "/*");
  12. registration.addInitParameter( "paramName", "paramValue");
  13. registration.setName( "MyFilter");
  14. registration.setOrder( 1);
  15. return registration;
  16. }
  17. public class MyFilter implements Filter {
  18. @Override
  19. public void destroy () {
  20. // TODO Auto-generated method stub
  21. }
  22. @Override
  23. public void doFilter (ServletRequest srequest, ServletResponse sresponse, FilterChain filterChain)
  24. throws IOException, ServletException {
  25. // TODO Auto-generated method stub
  26. HttpServletRequest request = (HttpServletRequest) srequest;
  27. System.out.println( "this is MyFilter,url :"+request.getRequestURI());
  28. filterChain.doFilter(srequest, sresponse);
  29. }
  30. @Override
  31. public void init (FilterConfig arg0) throws ServletException {
  32. // TODO Auto-generated method stub
  33. }
  34. }
  35. }

四、自定义property

在 Web 开发的过程中,我经常需要自定义一些配置文件,如何使用呢?

1、配置在application.properties中


    
    
  1. server. port= 8081
  2. #spring. profiles. active=dev
  3. # idea\uFF0Cproperties\u914D\u7F6E\u6587\u4EF6utf- 8
  4. # \uFFFD\uFFFD\uFFFD\uFFFDperson\uFFFD\uFFFD\u05B5
  5. person. last-name=\u5F20\u4E09${random. uuid}
  6. person. age=${random. int}
  7. person. birth= 2017/ 12/ 15
  8. person. boss= false
  9. person. maps. k1=v1
  10. person. maps. k2= 14
  11. person. lists=a,b,c
  12. person. dog. name=${person. hello:hello}_dog
  13. person. dog. age= 15

2、自定义配置类


    
    
  1. @Component
  2. public class NeoProperties {
  3. @Value("${person.last-name}")
  4. private String last-name; //此处last-name与lastName一样
  5. @Value("${person.age}")
  6. private int age;
  7. ...
  8. //省略getter settet方法
  9. }

3、log配置

配置输出的地址和输出级别


    
    
  1. logging. path=/user/ local/ log
  2. logging.level.com.favorites=DEBUG
  3. logging.level.org.springframework.web=INFO
  4. logging.level.org.hibernate=ERROR

path 为本机的 log 地址,logging.level 后面可以根据包路径配置不同资源的 log 级别

五、数据库操作

这里我们重点讲述MySQL、spring data jpa的使用。jpa是利用hibernate生成各种自动化的sql,如果只是简单的增删改查,基本不用手写,spring内部已经封装好了。

下面介绍一下在springboot中的使用

1、添加相关jar包


    
    
  1. <dependency>
  2. <groupId>org.springframework.boot </groupId>
  3. <artifactId>spring-boot-starter-data-jpa </artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>mysql </groupId>
  7. <artifactId>mysql-connector-java </artifactId>
  8. </dependency>

2、添加配置文件


    
    
  1. spring.datasource.url=jdbc:mysql://localhost:3306/test
  2. spring.datasource.username=root
  3. spring.datasource.password=root
  4. spring.datasource.driver-class-name=com.mysql.jdbc.Driver
  5. spring.jpa.properties.hibernate.hbm2ddl.auto=update
  6. spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
  7. spring.jpa.show-sql= true

其实这个 hibernate.hbm2ddl.auto 参数的作用主要用于:自动创。

验证数据库表结构有四个值:

  • create:每次加载hibernate时都会删除上一次生成的表,然后根据你的model类再重新来生成新表,哪怕;两次没有任何改变也要这样执行,这就是导致了数据库表数据丢失的一个重要原因。
  • create-drop:每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除了。
  • update:最常用的属性,第一次加载hibernate时根据model类会自动建立标的结构,以后加载hibernate时根据model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除之前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
  • validate:每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表践行比较,不会创建新表,但是会插入新值。

dialect 主要是指定生成表名的存储引擎为 InnoDBD
show-sql 是否打印出自动生成的 SQL,方便调试的时候查看

3、添加实体类和dao


    
    
  1. @Entity
  2. public class User implements Serializable {
  3. private static final long serialVersionUID = 1L;
  4. @Id
  5. @GeneratedValue
  6. private Long id;
  7. @Column(nullable = false, unique = true)
  8. private String userName;
  9. @Column(nullable = false)
  10. private String passWord;
  11. @Column(nullable = false, unique = true)
  12. private String email;
  13. @Column(nullable = true, unique = true)
  14. private String nickName;
  15. @Column(nullable = false)
  16. private String regTime;
  17. //省略getter settet方法、构造方法
  18. }

dao 只要继承 JpaRepository 类就可以,几乎可以不用写方法,还有一个特别有尿性的功能非常赞,就是可以根据方法名来自动的生成 SQL,比如findByUserName 会自动生成一个以 userName 为参数的查询方法,比如 findAlll 自动会查询表里面的所有数据,比如自动分页等等。。

Entity中不应是成列的字段得加 @Transient 注解,不加注解也会映射成列


    
    
  1. public interface UserRepository extends JpaRepository<User, Long> {
  2. User findByUserName (String userName);
  3. User findByUserNameOrEmail (String username, String email);
  4. }

4、测试


    
    
  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @SpringApplicationConfiguration(Application.class)
  3. public class UserRepositoryTests {
  4. @Autowired
  5. private UserRepository userRepository;
  6. @Test
  7. public void test () throws Exception {
  8. Date date = new Date();
  9. DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
  10. String formattedDate = dateFormat.format(date);
  11. userRepository.save( new User( "aa1", "aa@126.com", "aa", "aa123456",formattedDate));
  12. userRepository.save( new User( "bb2", "bb@126.com", "bb", "bb123456",formattedDate));
  13. userRepository.save( new User( "cc3", "cc@126.com", "cc", "cc123456",formattedDate));
  14. Assert.assertEquals( 9, userRepository.findAll().size());
  15. Assert.assertEquals( "bb", userRepository.findByUserNameOrEmail( "bb", "cc@126.com").getNickName());
  16. userRepository.delete(userRepository.findByUserName( "aa1"));
  17. }
  18. }

六、Thymeleaf 模板

Spring Boot 推荐使用 Thymeleaf 来代替 Jsp。

1、Thymeleaf介绍

Thymeleaf是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。 类似于JSP。它可以轻易的与springMVC框架进行集成作为web应用的模板引擎。与其他模板引擎相比, Thymeleaf  最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个web应用。

Thymeleaf 使用了自然的模板技术,这意味着 Thymeleaf 的模板语法不会破坏文档的结构,模板依旧是有效的XML文档。模板还可以用作工作原型, Thymeleaf 会在运行期替换掉静态值。

URL 在 Web 应用模板中占据着十分重要的地位,需要特别注意的是 Thymeleaf 对于 URL 的处理是通过语法 @{...} 来处理的。Thymeleaf 支持绝对路径 URL:

<a th:href="@{http://www.thymeleaf.org}">Thymeleaf</a>
    
    

条件求值

<a th:href="@{/login}" th:unless=${session.user != null}>Login</a>
    
    

 for循环


    
    
  1. <tr th:each="prod : ${prods}">
  2. <td th:text="${prod.name}">Onions </td>
  3. <td th:text="${prod.price}">2.41 </td>
  4. <td th:text="${prod.inStock}? #{true} : #{false}">yes </td>
  5. </tr>

2、页面即原型

  在传统 Java Web 开发过程中,前端工程师和后端工程师一样,也需要安装一套完整的开发环境,然后各类 Java IDE 中修改模板、静态资源文件,启动/重启/重新加载应用服务器,刷新页面查看最终效果。

但实际上前端工程师的职责更多应该关注页面,使用JSP很难做到这点,因为JSP必须在应用服务器中渲染完成后才能在浏览器中看到效果,而 Thymeleaf从跟不上解决了这个问题,通过属性进行模板渲染不会引入任何新的浏览器不能识别的标签,例如JSP中,不会再Tag内部写表达式。 整个页面直接作为 HTML 文件用浏览器打开,几乎就可以看到最终的效果,这大大解放了前端工程师的生产力,它们的最终交付物就是纯的 HTML/CSS/JavaScript 文件。

七、Gradle构建工具

spring项目建议使用 Maven/Gradle 进行构建项目 ,相比Maven来讲Gradle更简洁,而且Gradle更适合大型复杂项目的构建。Gradle吸收了maven和ant的特点,不过目前maven仍然是java界的主流,先了解一下嘛。

一个使用 Gradle 配置的项目:


    
    
  1. buildscript {
  2. repositories {
  3. maven { url "http://repo.spring.io/libs-snapshot" }
  4. mavenLocal()
  5. }
  6. dependencies {
  7. classpath( "org.springframework.boot:spring-boot-gradle-plugin:1.3.6.RELEASE")
  8. }
  9. }
  10. apply plugin: 'java' //添加 Java 插件, 表明这是一个 Java 项目
  11. apply plugin: 'spring-boot' //添加 Spring-boot支持
  12. apply plugin: 'war' //添加 War 插件, 可以导出 War 包
  13. apply plugin: 'eclipse' //添加 Eclipse 插件, 添加 Eclipse IDE 支持, Intellij Idea 为 "idea"
  14. war {
  15. baseName = 'favorites'
  16. version = '0.1.0'
  17. }
  18. sourceCompatibility = 1.7 //最低兼容版本 JDK1.7
  19. targetCompatibility = 1.7 //目标兼容版本 JDK1.7
  20. repositories { // Maven 仓库
  21. mavenLocal() //使用本地仓库
  22. mavenCentral() //使用中央仓库
  23. maven { url "http://repo.spring.io/libs-snapshot" } //使用远程仓库
  24. }
  25. dependencies { // 各种 依赖的jar包
  26. compile( "org.springframework.boot:spring-boot-starter-web:1.3.6.RELEASE")
  27. compile( "org.springframework.boot:spring-boot-starter-thymeleaf:1.3.6.RELEASE")
  28. compile( "org.springframework.boot:spring-boot-starter-data-jpa:1.3.6.RELEASE")
  29. compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.6'
  30. compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.4'
  31. compile( "org.springframework.boot:spring-boot-devtools:1.3.6.RELEASE")
  32. compile( "org.springframework.boot:spring-boot-starter-test:1.3.6.RELEASE")
  33. compile 'org.webjars.bower:bootstrap:3.3.6'
  34. compile 'org.webjars.bower:jquery:2.2.4'
  35. compile( "org.webjars:vue:1.0.24")
  36. compile 'org.webjars.bower:vue-resource:0.7.0'
  37. }
  38. bootRun {
  39. addResources = true
  40. }

八、 WebJars

WebJars 是一个很神奇的东西,可以让大家以jar包的形式来使用前端的各种框架、组件。

1、什么是 WebJars

WebJars是将客户端资源打包成jar包文件,以对资源进行统一依赖管理。 WebJars 的jar包部署在maven中央仓库上。

2、为什么使用

我们在开发java web项目的时候会使用Maven、 Gradle等构建工具以实现对jar包版本依赖管理,以及项目的自动化管理,但是对于JavaScript、css等前端资源包,我们只能采用拷贝到webapp下的方式,这样做就无法对这些资源进行依赖管理,那么WebJars就提供给我们这些前端资源的jar包资源,我们就可以进行依赖管理了。

3、如何使用

(1)添加依赖


    
    
  1. <dependency>
  2. <groupId>org.webjars </groupId>
  3. <artifactId>vue </artifactId>
  4. <version>2.5.16 </version>
  5. </dependency>

(2)页面引入

<link th:href="@{/webjars/bootstrap/3.3.6/dist/css/bootstrap.css}" rel="stylesheet"></link>
    
    

九、CRUD

已经完成了springboot的CRUD

关键的代码贴出来,分享一下吧

1、先看一下项目架构

2、扩展SpringMVC的功能


    
    
  1. package com.springboot.config;
  2. import com.springboot.component.LoginHandlerInterceptor;
  3. import com.springboot.component.MyLocaleResolver;
  4. import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
  5. import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8. import org.springframework.web.servlet.LocaleResolver;
  9. import org.springframework.web.servlet.config.annotation.EnableWebMvc;
  10. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  11. import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
  12. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  13. //使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能
  14. //@EnableWebMvc 不要接管SpringMVC
  15. @Configuration
  16. public class MyMvcConfig extends WebMvcConfigurerAdapter {
  17. @Override
  18. public void addViewControllers (ViewControllerRegistry registry) {
  19. // super.addViewControllers(registry);
  20. //浏览器发送 /atguigu 请求来到 success
  21. registry.addViewController( "/atguigu").setViewName( "success");
  22. }
  23. //所有的WebMvcConfigurerAdapter组件都会一起起作用
  24. @Bean //将组件注册在容器
  25. public WebMvcConfigurerAdapter webMvcConfigurerAdapter (){
  26. WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
  27. @Override
  28. public void addViewControllers (ViewControllerRegistry registry) {
  29. registry.addViewController( "/").setViewName( "login");
  30. registry.addViewController( "/index.html").setViewName( "login");
  31. registry.addViewController( "/main.html").setViewName( "dashboard");
  32. }
  33. //注册拦截器
  34. @Override
  35. public void addInterceptors (InterceptorRegistry registry) {
  36. //super.addInterceptors(registry);
  37. //静态资源; *.css , *.js
  38. //SpringBoot已经做好了静态资源映射
  39. // registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
  40. // .excludePathPatterns("/index.html","/","/user/login");
  41. }
  42. };
  43. return adapter;
  44. }
  45. @Bean
  46. public LocaleResolver localeResolver (){
  47. return new MyLocaleResolver();
  48. }
  49. }

3、controller


    
    
  1. package com.springboot.controller;
  2. import com.springboot.dao.DepartmentDao;
  3. import com.springboot.dao.EmployeeDao;
  4. import com.springboot.entities.Department;
  5. import com.springboot.entities.Employee;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.stereotype.Controller;
  8. import org.springframework.ui.Model;
  9. import org.springframework.web.bind.annotation.*;
  10. import java.util.Collection;
  11. @Controller
  12. public class EmployeeController {
  13. @Autowired
  14. EmployeeDao employeeDao;
  15. @Autowired
  16. DepartmentDao departmentDao;
  17. //查询所有员工返回列表页面
  18. @GetMapping("/emps")
  19. public String list (Model model){
  20. Collection<Employee> employees = employeeDao.getAll();
  21. //放在请求域中
  22. model.addAttribute( "emps",employees);
  23. // thymeleaf默认就会拼串
  24. // classpath:/templates/xxxx.html
  25. return "emp/list";
  26. }
  27. //来到员工添加页面
  28. @GetMapping("/emp")
  29. public String toAddPage (Model model){
  30. //来到添加页面,查出所有的部门,在页面显示
  31. Collection<Department> departments = departmentDao.getDepartments();
  32. model.addAttribute( "depts",departments);
  33. return "emp/add";
  34. }
  35. //员工添加
  36. //SpringMVC自动将请求参数和入参对象的属性进行一一绑定;要求请求参数的名字和javaBean入参的对象里面的属性名是一样的
  37. @PostMapping("/emp")
  38. public String addEmp (Employee employee){
  39. //来到员工列表页面
  40. System.out.println( "保存的员工信息:"+employee);
  41. //保存员工
  42. employeeDao.save(employee);
  43. // redirect: 表示重定向到一个地址 /代表当前项目路径
  44. // forward: 表示转发到一个地址
  45. return "redirect:/emps";
  46. }
  47. //来到修改页面,查出当前员工,在页面回显
  48. @GetMapping("/emp/{id}")
  49. public String toEditPage (@PathVariable("id") Integer id,Model model){
  50. Employee employee = employeeDao.get(id);
  51. model.addAttribute( "emp",employee);
  52. //页面要显示所有的部门列表
  53. Collection<Department> departments = departmentDao.getDepartments();
  54. model.addAttribute( "depts",departments);
  55. //回到修改页面(add是一个修改添加二合一的页面);
  56. return "emp/add";
  57. }
  58. //员工修改;需要提交员工id;
  59. @PutMapping("/emp")
  60. public String updateEmployee (Employee employee){
  61. System.out.println( "修改的员工数据:"+employee);
  62. employeeDao.save(employee);
  63. return "redirect:/emps";
  64. }
  65. //员工删除
  66. @DeleteMapping("/emp/{id}")
  67. public String deleteEmployee (@PathVariable("id") Integer id){
  68. employeeDao.delete(id);
  69. return "redirect:/emps";
  70. }
  71. }

4、前端页面

以list.html为例,使用springboot特带的Thymeleaf模板引擎

(1)引入

xmlns:th="http://www.thymeleaf.org"
    
    

(2)关键的js、css引入


    
    
  1. script type= "text/javascript" src= "asserts/js/jquery-3.2.1.slim.min.js" th:src= "@{/webjars/jquery/3.3.1/jquery.js}"></script>
  2. <script type="text/javascript" src="asserts/js/popper.min.js" th:src="@{/webjars/popper.js/1.11.1/dist/popper.js}"></script>
  3. <script type="text/javascript" src="asserts/js/bootstrap.min.js" th:src="@{/webjars/bootstrap/4.0.0/js/bootstrap.js}"></script>
  4. <!-- Icons -->
  5. <script type="text/javascript" src="asserts/js/feather.min.js" th:src="@{/asserts/js/feather.min.js}"></script>

(3)form表单提交


    
    
  1. <div class="container-fluid">
  2. <div class="row">
  3. <!--引入侧边栏-->
  4. <div th:replace="commons/bar::#sidebar(activeUri='emps')"> </div>
  5. <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
  6. <h2> <a class="btn btn-sm btn-success" href="emp" th:href="@{/emp}">员工添加 </a> </h2>
  7. <div class="table-responsive">
  8. <table class="table table-striped table-sm">
  9. <thead>
  10. <tr>
  11. <th># </th>
  12. <th>lastName </th>
  13. <th>email </th>
  14. <th>gender </th>
  15. <th>department </th>
  16. <th>birth </th>
  17. <th>操作 </th>
  18. </tr>
  19. </thead>
  20. <tbody>
  21. <tr th:each="emp:${emps}">
  22. <td th:text="${emp.id}"> </td>
  23. <td>[[${emp.lastName}]] </td>
  24. <td th:text="${emp.email}"> </td>
  25. <td th:text="${emp.gender}==0?'女':'男'"> </td>
  26. <td th:text="${emp.department.departmentName}"> </td>
  27. <td th:text="${#dates.format(emp.birth, 'yyyy-MM-dd HH:mm')}"> </td>
  28. <td>
  29. <a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.id}">编辑 </a>
  30. <button th:attr="del_uri=@{/emp/}+${emp.id}" class="btn btn-sm btn-danger deleteBtn">删除 </button>
  31. </td>
  32. </tr>
  33. </tbody>
  34. </table>
  35. </div>
  36. </main>
  37. <form id="deleteEmpForm" method="post">
  38. <input type="hidden" name="_method" value="delete"/>
  39. </form>
  40. </div>
  41. </div>

(4)jQuery实现


    
    
  1. <script>
  2. $( ".deleteBtn"). click( function( ){
  3. //删除当前员工的
  4. $( "#deleteEmpForm"). attr( "action",$( this). attr( "del_uri")). submit();
  5. return false;
  6. });
  7. </script>

5、实现效果

上一篇:Spring Boot入门篇 | Spring Boot 1

下一篇:Thymeleaf的基本语法 | Spring Boot 3

关注公众号,回复1024,获取Java学习路线思维导图、加入万粉计划交流群

    <div id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"><div class="blog_extension blog_extension_type1" id="blog_extension">
      <div class="blog_extension_card" data-report-click="{&quot;spm&quot;:&quot;1001.2101.3001.6470&quot;}" data-report-view="{&quot;spm&quot;:&quot;1001.2101.3001.6470&quot;}">
        <div class="blog_extension_card_left">
        <img src="https://img-blog.csdnimg.cn/2f3d245fb4f14fae8a423d0c159becfe.png" alt="">
      </div>
        <div class="blog_extension_card_cont">
          <div class="blog_extension_card_cont_l">
            <span class="text">哪吒编程</span>
            <div class="blog_extension_card_cont_r">
              <img class="weixin" src="https://g.csdnimg.cn/extension-box/1.1.5/image/weixin.png" alt="">
              <span>微信公众号</span>
              <img class="go" src="https://g.csdnimg.cn/extension-box/1.1.5/image/ic_move.png" alt="">
            </div>
          </div>
          <span class="style">领取学习资料、大厂面试真题、职业规划</span>
        </div>
      </div></div></div>
</article>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值