springboot

小新
2022-03-20 / 0 评论 / 341 阅读 / 正在检测是否收录...

spring-boot Web开发

配置静态文件

  1. 可以使用以下方式处理静态资源

webjars : http://localhost:8080/webjars

  • resources
  • static
  • public

http://localhost:8080/

以上文件可直接存放

  1. 优先级 :resources > static (默认) > public

模板引擎

templates 只能controller 层访问 : 需要模板引擎的支持 需要 Thymeleaf 依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

页面存放在templates文件中

  1. 首页配置:所有页面的静态资源都需要使用Thymeleaf接管;@{}
  2. 加上

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

配置跳转

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //类似于@RequestMapping("/")
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
    }
}

拦截器

package com.xin.config;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*登录拦截器*/
public class LoginHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取用户的sessoin
        Object loginUser = request.getSession().getAttribute("loginUser");
        //判断是否登录
        if(loginUser == null){
            request.setAttribute("msg","未监测登录,请重新登录");
            //转发
            request.getRequestDispatcher("/index.html").forward(request,response);
            return false;
        }else {
            return true;
        }
    }
}

配置拦截器

config 包下

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new             LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login");
}

addPathPatterns:需要拦截

excludePathPatterns:不需要拦截 注意: 还需要填写css , js 资源等.

Thymeleaf 语法

spring.thymeleaf.cache=false //关闭模板引擎缓存

1. 标签复用

th:fragment="topbar" 需要重复的标签

th:insert="~{dashboard::topbar}" 插入标签

th:replace="~{存放公共标签的地址 :: topbar}"

th:include 和 th:replace都是加载代码块内容,但是还是有所不同

  • th:include:加载模板的内容: 读取加载节点的内容(不含节点名称),替换div内容
  • th:replace:替换当前标签为模板中的标签,加载的节点会整个替换掉加载他的div
<!-- th:fragment 定义用于加载的块 -->
<span th:fragment="pagination"> 
the public pagination
</span>
================= th:include 和 th:replace============================
<!-- 加载模板的内容: 读取加载节点的内容(不含节点名称),替换<div>的内容 -->
<div th:include="pagination::pagination">1</div>
<!-- 替换当前标签为模板中的标签: 加载的节点会整个替换掉加载他的<div>  -->
<div th:replace="pagination::pagination">2</div>

结果:

<!-- 加载模板的内容: 读取加载节点的内容(不含节点名称),替换<div>的内容 -->
<div> the public pagination</div>
<!-- 替换当前标签为模板中的标签: 加载的节点会整个替换掉加载他的<div>  -->
<span> the public pagination</span>

if-- 判断空 例:

<!--如果msg等于null 就不显示-->
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>

restFul 获取参数

@PathVariable("变量")

异常错误页面

templates文件 ==> error文件==> 页面

lombok 实体类注解

  • 是一个在Java开发过程中用注解的方式,简化了 JavaBean 的编写,避免了冗余和样板式代码而出现的插件,让编写的类更加简洁。

JDBC配置教程

导入依赖 : 使用idea 创建的时候就可以直接导入 JDBC , MySql Driver

首先配置yaml 配置文件

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.jdbc.Driver

Controller 层测试

package com.xin.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

@RestController
public class JDBCController {
    @Autowired
    JdbcTemplate jdbcTemplate;

    //查询全部用户 (这里没有用实体类,用的map代替)
    @RequestMapping("/userList")
    public List<Map<String,Object>> userList(){
        String sql = "select * from user";
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
        return maps;
    }

    //添加一条数据
    @RequestMapping("/addUser")
    public String addUser(){
        String sql = "insert into user(name,pwd) values('小新','123123')";
        jdbcTemplate.update(sql);
        return "添加成功!";
    }

    //更新一条数据
    @RequestMapping("/updeUser/{id}")
    public String updeUser(@PathVariable("id") int id){
        String sql = "update user set name=?,pwd=? where id ="+id;
        Object[] objects = new Object[2];
        objects[0] = "小新2号";
        objects[1] = "123456";
        jdbcTemplate.update(sql,objects);
        return "修改成功!";
    }

    //删除一条数据
    @RequestMapping("/delUser/{id}")
    public String delUser(@PathVariable("id") int id){
        String sql = "delete from user where id =?";
        jdbcTemplate.update(sql,id);
        return "删除成功!";
    }

}

Druid 数据库连接池

这里没有做笔记,去网上直接找

Mybatis 整合

  1. 导入相对应的包
  2. 配置文件
  3. mybatis配置
  4. 编写sql
  5. service层调用dao层
  6. controller 调用service层

image-20220317220622182

需要整合包

mybatis-spring-boot-starter

配置文件 (application.properties)

spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver


#整合mybatis
mybatis.type-aliases-package=com.xin.pojo
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

实体类 注解

package com.xin.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;
}

其余步骤和之前mybatis 一样

注意: Mapping包下的类 需要注解

@Mapper
@Repository
public interface UserMapper {
    /**
     * 查询全部信息
     * @return
     */
    List<User> selUserList();


    /**
     * 查询单个
     * @param id
     * @return
     */
    User selUserById(int id);
}

Mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xin.mapper.UserMapper">
    <select id="selUserList" resultType="user">
        select * from user
    </select>


    <select id="selUserById" resultType="user">
        select * from user where id = #{id}
    </select>

</mapper>

springSecurity(安全)

shiro

shiro主要有三大功能模块
  1. Subject:主体,一般指用户。
  2. SecurityManager:安全管理器,管理所有Subject,可以配合内部安全组件。(类似于SpringMVC中的DispatcherServlet)
  3. Realms:用于进行权限信息的验证,一般需要自己实现。
细分功能
  1. Authentication:身份认证/登录(账号密码验证)。
  2. Authorization:授权,即角色或者权限验证。
  3. Session Manager:会话管理,用户登录后的session相关管理。
  4. Cryptography:加密,密码加密等。
  5. Web Support:Web支持,集成Web环境。
  6. Caching:缓存,用户信息、角色、权限等缓存到如redis等缓存中。
  7. Concurrency:多线程并发验证,在一个线程中开启另一个线程,可以把权限自动传播过去。
  8. Testing:测试支持;
  9. Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问。
  10. Remember Me:记住我,登录后,下次再来的话不用登录了。
springboot 和shiro + JDBC 整合的步骤
  1. 创建依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.xin</groupId>
    <artifactId>springboot-shiro</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-shiro</name>
    <description>springboot-shiro</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!-- mybatis-spring-boot-starter -->
        <!--自研-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  1. 权限对应的实体类

这里不做笔记展示

​ 还要写Mapper 、Service

  1. 自定义Realm用于查询用户的角色和权限信息并保存到权限管理器:
package com.xin.config;
import com.xin.pojo.User;
import com.xin.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

//自定义的Realm
public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了授权");

        //SimpleAuthorizationInfo
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        //拿到当前用户对象
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User) subject.getPrincipal(); //拿到User对象 ,强转


        //设置当前用户的权限
        info.addStringPermission(currentUser.getPerms());

        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken Token) throws AuthenticationException {
        System.out.println("执行了认证");
        //前端传输 封装的
        UsernamePasswordToken token = (UsernamePasswordToken) Token;

        //连接数据,取数据
        User user = userService.selUserByName(token.getUsername());
        if(user==null){
            return null;
        }


        //密码认证, shiro做 ,加密了
        //这里的user参数传递 是为了让授权获取到
        return new SimpleAuthenticationInfo(user,user.getPwd(),"");
    }
}
  1. ShiroConfig.java
package com.xin.config;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    //3.shiroFilterFactorybean
    @Bean
     public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
         ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
         //设置安全管理器
         bean.setSecurityManager(defaultWebSecurityManager);
         //添加shiro的内置过滤器
        /*
              anon:无需认证就可以访问
              authc:必须认证了才能访问
              user:必须拥有 记住我 功能才能用
              perms:拥有对某个资源的权限才能访问
              role:拥有某个角色权限才能访问
         */

        //拦截
        Map<String, String> filterMap = new LinkedHashMap<>();

        //授权拦截
        filterMap.put("/user/add","perms[user:add]");
        filterMap.put("/user/upda","perms[user:upda]");

        filterMap.put("/user/*","authc");//user下页面必须要认证后才能拿访问
        bean.setFilterChainDefinitionMap(filterMap);

        //设置登录页面的跳转
        bean.setLoginUrl("/toLogin");

        //设置没有权限跳转页面
        bean.setUnauthorizedUrl("/perms");
        return bean;

     }
    //2.DafaultWebSecurityManger
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager SecurityManager = new DefaultWebSecurityManager();
        //关联userRealm
        SecurityManager.setRealm(userRealm);
        return SecurityManager;
    }

    //1.创建 realm 对象,需要自定义
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }
}
  1. Controller
package com.xin.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MyController {

    @RequestMapping({"/","/index"})
    public String toindex(Model model){
        model.addAttribute("msg","Hello,shiro");
        return "index";
    }

    @RequestMapping("user/add")
    public String add(){
        return "user/add";
    }

    @RequestMapping("user/upda")
    public String upda(){
        return "user/upda";
    }


    @RequestMapping("/toLogin")
    public String toLogin(){
        return "login";
    }


    @RequestMapping("login")
    public String login(String username,String password,Model model){
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();

        //封装用户的登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);

        try {
            //执行登录方法, 如果没有异常就直接登录
            subject.login(token);
            return "index";
        }catch (UnknownAccountException e){
            model.addAttribute("msg","用户名不存在");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("msg","密码错误!");
            return "login";
        }
    }


    @RequestMapping("/perms")
    @ResponseBody
    public String perms(){
        return "对不起,你没有访问权限";
    }
}
  1. 目录结构图

image-20220320195213625

shiro 整合 Thymeleaf

导入整合依赖

<dependency>
    <groupId>com.github.theborakompanioni</groupId>
    <artifactId>thymeleaf-extras-shiro</artifactId>
    <version>2.1.0</version>
</dependency>

ShiroConfig 中配置整合

//整合shiro : 用来整合shiro 和 thymeleaf
@Bean
public ShiroDialect getShiroDialect(){
    return new ShiroDialect();
}

html页面中加上

xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"

前端代码

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h1>首页</h1>
<div th:if="${session.loginUser==null}">
    <a th:href="@{/toLogin}">登录</a>
</div>
<p th:text="${msg}"></p>
<hr>

<div shiro:hasPermission="user:add">
    <a th:href="@{/user/add}">add</a>
</div>

<div shiro:hasPermission="user:upda">
    <a th:href="@{user/upda}">upda</a>
</div>

</body>
</html>
0

评论 (0)

取消