JAVA WEB 个人备忘录

mysql

创建数据库

-- 创建数据库: 创建一个名为db1的数据库
create database db1;
​
​
-- 切换数据库:
use db1;

增删改数据

所有字段插入值
insert into tb_emp values (null,'忘了爱','111','杨宁',1,'/img',1,'2002-12-21',now(),now());
批插
insert into tb_emp values (null,'忘了爱1','111','杨宁2',1,'/img',1,'2002-12-21',now(),now())
                        ,(null,'忘了爱2','111','杨宁3',1,'/img',1,'2002-12-21',now(),now());
修改
update tb_emp set name = '传智',entrydate='2022-01-01' where id =1;
删除
delete from tb_emp where id = 1;

查数据

交叉连接
select * from emp,dept;
内连接
select * from emp e inner join dept d on e.dept_id = d.id;
左外连接
select * from emp e left join dept d on e.dept_id = d.id;
右外连接
select * from emp e right join dept d on e.dept_id = d.id;
子查询
-- 1: 查询工资小于平均工资的员工有哪些?(子查询结果为一个值  标量子查询)
select * from emp where salary < (select avg(salary) from emp);
-- 2: 查询工资大于5000的员工,所在部门的名字 (子查询结果为多个值  列子查询)
select name from dept where id in(select distinct dept_id from emp where salary > 5000);
-- 3: 查询出2011年以后入职的员工信息,包括部门信息 (子查询结果为一张表   表子查询)
select * from (select * from emp where join_date >= '2011-01-01') as l
    left join dept as d on l.dept_id = d.id;
复杂查询
​
# 菜品表:dish、分类表:category、套餐表:setmeal
​
-- 1. 查询价格低于 10元 的菜品的名称 、价格 及其 菜品的分类名称
select d.name,d.price,c.name from dish d
    inner join category c on d.category_id = c.id where d.price <10;
​
-- 2. 查询所有价格在 10元(含)到50元(含)之间 且 状态为'起售'的菜品名称、价格 及其 菜品的分类名称
# (即使菜品没有分类, 也需要将菜品查询出来).
select d.name,d.price,c.name from dish d left join category c on d.category_id = c.id
where d.price between 10 and 50 and d.status = 1;
​
-- 3. 查询出 "商务套餐A" 中包含了哪些菜品 (展示出套餐名称、价格, 包含的菜品名称、价格、份数)
# 三表关联,重复使用join
select s.name,s.price,d.name,d.price,sd.copies
from setmeal s
         join setmeal_dish sd on s.id = sd.setmeal_id
         join dish d on d.id = sd.dish_id
where s.name = '商务套餐A';
​
-- 4. 查询出低于菜品平均价格的菜品信息 (展示出菜品名称、菜品价格)
select name,price from dish where price < (select avg(price) from dish) order by price;
​
-- 5. 查询每个分类下最贵的菜品, 展示出分类的名称、最贵的菜品的价格
select c.name,max(d.price)
from dish d
         join category c on d.category_id = c.id
group by c.name;
​
-- 6. 查询各个分类下状态为'起售' , 并且该分类下 菜品总数量大于等于3的分类名称
select c.name,count(*) count
from category c
         join dish d on c.id = d.category_id
where c.status = 1
group by c.name
having count >=3;

多表查询关键字

  1. INNER JOIN: 内连接,返回两个表中匹配的行。

  2. LEFT JOIN: 左连接,返回左表中的所有行,以及右表中与左表匹配的行。

  3. RIGHT JOIN: 右连接,返回右表中的所有行,以及左表中与右表匹配的行。

  4. FULL JOIN: 全连接,返回左表和右表中的所有行,如果没有匹配的行,则以NULL填充。

  5. CROSS JOIN: 交叉连接,返回两个表中所有可能的组合。

此外,还有一些其他的关键字和子句可以在多表查询中使用:

  1. ON: 在连接时指定条件进行匹配,使用语法如下:SELECT * FROM table1 JOIN table2 ON table1.column = table2.column

  2. USING: 在连接时指定某些列进行匹配,使用语法如下:SELECT * FROM table1 JOIN table2 USING (column)

  3. WHERE: 在查询中添加条件来过滤结果集。

  4. GROUP BY: 按照某个列或者多个列对结果进行分组。

  5. HAVING: 在GROUP BY之后使用条件过滤结果。

分组过滤

分组过滤: select 分组字段,聚合函数() from 表名 group by 分组字段名 having 分组后过滤条件

排序

排序: select 字段列表 from 表名 order by 字段1 排序方式1 , 字段2 排序方式2

ASC:升序(默认值)

DESC:降序

分页

分页: select 字段列表 from 表名 limit 起始索引, 查询记录数

  1. 排序: order by 列 desc

  2. 截取: limit 开始,几个

  3. 聚合函数: count(列)

  4. 分组: group by 列

  5. 过滤: having 过滤条件

  6. 普通条件: where

外键

创建表之后单独添加
# alter table 表名 add [constraint 约束名]  foreign key (列名)  references  主表(主键)
alter table student
    add constraint class_id_fk foreign key (class_id) references class (id);
创建表的时候,添加外键
create table user_card(
    id int unsigned primary key  auto_increment,
    nationality varchar(10) not null ,
    birthday date not null ,
    idcard char(18) not null ,
    issued varchar(20) not null ,
    expire_begin date not null ,
    expire_end date,
    user_id int unsigned comment '用户id',
#     创建表的时候,添加外键 (user_id 和 user表的id)
    constraint userid_id_fk foreign key (user_id) references user(id)
);

mybatis

配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <settings>
        <!--在控制台输出发送的sql日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>

            <!--目前只关注这部分内容,它的作用就是声明要连接的数据信息-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="1234"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--声明含有sql的接口所在包-->
        <package name="com.itheima.mapper"/>
    </mappers>
</configuration>

Mapper

// 1. 这是一个接口
// 2. 接口名:操作的表名+Mapper
public interface UserMapper {

    // #{}里面的内容
    // 1. 如果参数是对象类型,#{}写的是对象的属性名
    @Insert("insert into user values (null,#{name},#{age},#{gender},#{phone})")
    void save(User user);

    // @Options
    // useGeneratedKeys 拿到自增主键
    // keyProperty 指定哪个字段是主键
    @Options(useGeneratedKeys = true, keyProperty = "id")
    @Insert("insert into user values (null,#{name},#{age},#{gender},#{phone})")
    void save2(User user);

    @Update("update user set name = #{name},age=#{age},gender=#{gender},phone = #{phone} where id=#{id} ")
    void update(User user);

    @Delete("delete from user where id = #{id}")
    void delete(Integer id);


    @Delete("delete from user where name = #{name}")
    void deleteByName1(String name);

    @Delete("delete from user where name = ${name}")
    void deleteByName2(String name);
}

测试类

public class UserMapperTest {
    @Test
    public void testSave() throws IOException {
        // 1. 创建对象
        User user = new User();
        user.setName("张三");
        user.setAge(18);
        user.setGender(1);
        user.setPhone("15515847153");

        // 工具类获取sqlSession
        SqlSession sqlSession = MyBatisUtil.getSqlSession();

        // 获取UserMapper对象,调用方法
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        userMapper.save(user);

        // 工具类关闭sqlSession
        MyBatisUtil.close(sqlSession);
    }


    @Test
    public void testDeleteByName1() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();

        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        userMapper.deleteByName1("张三");
        // delete from user where name = '张三'

        MyBatisUtil.close(sqlSession);
    }

    @Test
    public void testDeleteByName2() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();

        // 用户名叫作:'李四' or id>1
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        userMapper.deleteByName2(" '李四' or id>1"); // ${}会产生sql注入问题
        // delete from user where name = '李四' or id>1

        MyBatisUtil.close(sqlSession);
    }
}

xml写sql

foreach
    <!--
* collection:集合名称
* item:集合遍历出来的元素
* separator:每一次遍历使用的分隔符
* open: 遍历开始前拼接的片段
* close:遍历结束后拼接的片段
 delete from emp where id in (1,2,3)
    -->
    <delete id="deleteByIds">
        delete from emp where id in
       <foreach collection="ids" item="id" separator="," open="(" close=")">
           #{id}
       </foreach>
    </delete>
sql片段
    <!--ctrl + alt + L:格式化代码-->
    <!--
* 定义SQL片段:  <sql id="selectUser"></sql>
* 引用SQL片段:  <include refid="selectUser"></include>
    -->
    <sql id="selectUser">
        select id,
               username,
               password,
               name,
               gender,
               image,
               job,
               entrydate as ed,
               dept_id,
               create_time,
               update_time
        from emp
    </sql>

    <!--id:哪个方法-->
    <!--resultType:方法返回值类型(sql结果数据类型)-->
    <select id="findById" resultType="com.itheima.domain.Emp">
        <include refid="selectUser"></include>
        where id = #{id}
    </select>
查询&修改
    <!--
        字符串需要跟null和空串比较
        其他类型只要跟null比较

        if:使用test进行条件判断,只有条件成立,条件中的sql才会生效
        where:只会在<where>标签内部有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或OR。
    -->
    <select id="finByCondition" resultType="com.itheima.domain.Emp">
        <include refid="selectUser"/>
        <where>
            <if test="name != null and name !='' ">
               and name like concat('%',#{name},'%')
            </if>
            <if test="gender != null">
                and gender = #{gender}
            </if>
            <if test="begin != null and end != null">
                and entrydate between #{begin} and #{end}
            </if>
        </where>
    </select>

    <!--set:动态地在set代码块之前加入SET关键字,并删掉set代码块中最后一个多余的逗号(用在update语句中)-->
    <!--ctrl + shift + / 生成快捷键 -->
    <update id="update">
        update emp
        <set>
            <if test="username != null and username != '' ">
                username = #{username},
            </if>
            <if test="name != null and  name != '' ">
                name = #{name},
            </if>
            <if test="gender != null">
                gender = #{gender},
            </if>
            <if test="job != null">
                job = #{job},
            </if>
            <if test="ed != null">
                entrydate = #{ed},
            </if>
            <if test="deptId != null">
                dept_id = #{deptId},
            </if>
        </set>
        where id = #{id}
    </update>

驼峰映射

    <settings>
        <!--在控制台输出发送的sql日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>

        <!--驼峰映射-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

Mapper接口映射

    <mappers>
        <!--声明含有sql的接口所在包-->
        <package name="com.itheima.mapper"/>
    </mappers>

resultMap

    <resultMap id="empResultMap" type="com.itheima.domain.Emp">
        <id property="id" column="id"></id> <!--设置主键-->
        <!--result:建立映射关系-->
        <!--property:实体类属性,column:数据库表字段-->
        <result property="username" column="username"></result>
        <result property="password" column="password"></result>
        <result property="name" column="name"></result>
        <result property="gender" column="gender"></result>
        <result property="image" column="image"></result>
        <result property="job" column="job"></result>
        <result property="ed" column="entrydate"></result>
        <result property="deptId" column="dept_id"></result>
        <result property="createTime" column="create_time"></result>
        <result property="updateTime" column="update_time"></result>
    </resultMap>
    
    
    
    
        <!--id:哪个方法-->
    <!--resultType:方法返回值类型(sql结果数据类型)-->
    <select id="findById" resultType="com.itheima.domain.Emp">
        <include refid="selectUser"></include>
        where id = #{id}
    </select>


    <!--resultMap:sql结果通过resultMap映射到实体类字段中-->
    <select id="selectAll" resultMap="empResultMap">
        select * from emp
    </select>

前端

js

函数定义
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>函数</title>
</head>
<body>
<!--定义一个函数(方法)实现两个数相加-->
<script>
    // 方式一:定义函数(方法)
    function add(a, b) {
        return a + b
    }

    let result = add(1, 2)
    console.log(result)

    // 方式二:定义函数
    let add2 = function (a, b) {
        return a + b
    }
    let result2 = add2(1,2);
    console.log(result2)

</script>
</body>
</html>
事件绑定
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>事件绑定</title>
</head>
<body>
<input type="button" value="按钮1" οnclick="tan()"> <br>
<input type="button" value="按钮2" id="btn"> <br>
<!--
    事件绑定有两种方式:
    1. 通过 HTML标签中的事件属性进行绑定
    2. 通过 DOM 元素属性绑定
-->
<script>
    // 1. 通过 HTML标签中的事件属性进行绑定
    function tan() {
        alert('按钮一被点击了')
    }

    // 2. 通过 DOM 元素属性绑定 (document代表当前页面对象)
    document.getElementById('btn').onclick = function () {
        alert('按钮二被点击了')
    }

</script>

</body>
</html>
事件绑定综合案例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>案例:页面交互</title>
    <!--
        常用事件:
            1. onfocus 获取焦点
            2. onblur 失去焦点
            3. onchange 表单控件的值改变时
            4. onclick 鼠标单击
            5. onload 页面加载完成
    -->

    <script>
        //5. 将js代码调整到页面的head部分,使其依旧可以运行
        window.onload = function (){

            //1. 当姓名框获得焦点之后,设置其value值为传智
            document.getElementById('username').onfocus = function () {
                // document.getElementById('username').value = '传智'
                this.value = '传智' // this代表当前对象
            }

            //2. 当姓名框失去焦点之后,设置其value值为黑马
            document.getElementById('username').onblur = function () {
                this.value = '黑马'
            }

            //3. 当学历发生变化的时候,在控制台打印出变化之后的value值
            document.getElementById('edu').onchange = function () {
                console.log(this.value)
            }

            //4. 当鼠标点击按钮时,弹窗显示被点击了
            document.getElementById('btn').onclick = function () {
                alert('被点击了')
            }

        }



    </script>
</head>
<body>
姓名 <input type="text" id="username"><br/>
学历
<select name="edu" id="edu">
    <option value="0">请选择</option>
    <option value="1">本科</option>
    <option value="2">大专</option>
</select>
<br/>
<button id="btn">按钮</button>


</body>
</html>

Servlet

路径

@WebServlet("/login")

req & resp

@WebServlet("/requestServlet")
public class RequestServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 请求参数编码,设置为UTF-8
        req.setCharacterEncoding("UTF-8");

        String name = req.getParameter("name");
        String age = req.getParameter("age");
        System.out.println("name=" + name + " age=" + age);

        String[] hobbies = req.getParameterValues("hobby");
        System.out.println(Arrays.toString(hobbies));
    }
}
@WebServlet("/responseServlet")
public class ResponseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 响应成功状态码
        resp.setStatus(200);

        // 设置响应头
        resp.setContentType("text/html;charset=utf-8");

        // 返回数据
        PrintWriter writer = resp.getWriter();
        writer.write("hello servlet");
    }
}

postman

模拟浏览器发起请求

http://localhost:8080/requestServlet?name=张三&age=18

对象转json字符串 & json字符串转对象

<!--json转换工具-->
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.9</version>
</dependency>
Student student = new ObjectMapper().readValue(json, Student.class);
System.out.println(student);
Student student = studentService.findById(id);
String json = new ObjectMapper().writeValueAsString(student);

增删改查案例

@WebServlet("/studentServlet")
public class StudentServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String action = req.getParameter("action");
        if ("findAll".equals(action)) {
            // 1. 操作service层
            StudentService studentService = new StudentServiceImpl();
            List<Student> students = studentService.findAll();

            // 2. 把数据转为json字符串格式
            String json = new ObjectMapper().writeValueAsString(students);

            System.out.println(json);

            // 3. 返回数据给前端
            resp.getWriter().write(json);
        } else if ("save".equals(action)) {
            // 1. 以流的方式接收前端json数据
            ServletInputStream inputStream = req.getInputStream();
            String json = IoUtil.read(inputStream, "utf-8");

            // 2. 把json字符串转为对象
            Student student = new ObjectMapper().readValue(json, Student.class);
            System.out.println(student);

            // 3. 调用service层,添加学生
            StudentService studentService = new StudentServiceImpl();
            studentService.save(student);

            // 4. 返回ok
            resp.getWriter().write("OK");
        } else if ("deleteById".equals(action)) {
            String id = req.getParameter("id");

            StudentService studentService = new StudentServiceImpl();
            studentService.deleteById(id);

            resp.getWriter().write("OK");
        } else if ("findById".equals(action)) {
            String id = req.getParameter("id");

            StudentService studentService = new StudentServiceImpl();
            Student student = studentService.findById(id);

            String json = new ObjectMapper().writeValueAsString(student);
            resp.getWriter().write(json);
        } else if ("update".equals(action)) {
            ServletInputStream inputStream = req.getInputStream();
            String json = IoUtil.read(inputStream, "utf-8");

            Student student = new ObjectMapper().readValue(json, Student.class);
            System.out.println(student);

            StudentService studentService = new StudentServiceImpl();
            studentService.update(student);

            resp.getWriter().write("OK");
        }
    }
}

Spring

Spring整合Mybatis

依赖
    <dependencies>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <!--druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>
        <!--spring-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.16</version>
        </dependency>
        <!--spring-jdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.16</version>
        </dependency>
        <!--spring-mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.7</version>
        </dependency>
        <!--测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.16</version>
        </dependency>
    </dependencies>

配置类
@ComponentScan("com.itheima") // @ComponentScan 注解扫描范围
public class SpringConfig {

    // 1. 配置数据库连接池对象
    @Bean
    public DruidDataSource dataSource(){
        // 创建DruidDataSource对象
        DruidDataSource dataSource = new DruidDataSource();

        // 设置连接数据库的参数:driver(加载器)、路径、用户名、密码
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/spring");
        dataSource.setUsername("root");
        dataSource.setPassword("1234");
        return dataSource;
    }

    // 2. 配置mapper映射对象
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
        configurer.setBasePackage("com.itheima.mapper"); // 设置接口所在包名
        return configurer;
    }

    // 3. 配置SqlSessionFactoryBean
    // @Bean标注的方法如果需要参数,Spring会在自己的容器中查找,自动注入
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DruidDataSource dataSource){
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        return factoryBean;
    }
}

Spring写测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class DeptMapperTest {
    @Autowired
    private DeptService deptService;

    @Test
    public void testFindAll() {
        // 3. 验证deptService是否拿到;验证deptService是否拿到DeptMapper对象
        List<Dept> deptList = deptService.findAll();
        deptList.forEach(dept -> System.out.println(dept));
    }

    @Test
    public void deleteByIdTest() {
        deptService.deleteById(1);
    }

    @Test
    public void insertDept() {

        Dept dept = new Dept();
        dept.setId(6);
        dept.setName("网管部");
        dept.setCreateTime(LocalDateTime.now());
        dept.setUpdateTime(LocalDateTime.now());
        deptService.insertDept(dept);
    }

    @Test
    public void updateDept(){

        Dept dept = new Dept();
        dept.setId(5);
        dept.setName("外交部");
        deptService.updateDept(dept);
    }
}

Spring注解

@Component @Controller @Service @Repository标注在自己开发的类上,用于将当前类对象放入Spring容器
@Bean标注在配置类中的方法上,用于将方法的返回值对象放入Spring容器
@Autowired标注在类中的属性上,用于从Spring容器中获取属性的值
@Qualifier @Primary依赖注入时,根据一个接口查到了多个对象,使用这两个注解确定使用哪个对象
@Scope标注在类上,声明对象是单例还是多例
@Configuration标注在配置类上,Spring容器启动时会自动加载类中的配置
@ComponentScan标注在主配置类上,用于声明包扫描的范围

动态代理

JDK动态代理

被代理对象需要有接口

// jdk动态代理工厂
public class JDKProxyFactory {

    public static Object getProxy(Class clazz) {
        // 生成代理对象
        Object proxy = Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Logger logger = new Logger();
                Object obj = null;
                try {
                    // 前置增强
                    logger.m1();
                    // method.invoke:被代理的对象执行方法
                    obj = method.invoke(clazz.newInstance(), args);
                    // 后置增强
                    logger.m2();
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.m3();
                }
                return obj;
            }
        });
        return proxy;
    }
}

Cglib动态代理

被代理对象可以被继承

// Cglib动态代理 (基于继承)
public class CglibProxyFactory {

    public static Object getProxy(Class clazz){
        // 创建一个代理工具类
        Enhancer enhancer = new Enhancer();

        // 根据父类创建子类对象(认爹)
        enhancer.setSuperclass(clazz);
        // 调用代理对象的方法 (增强的代码写在这里)
        enhancer.setCallback(new InvocationHandler() {
            @Override
            // 参数一:代理对象本身(用不上)
            // 参数二:代理对象方法
            // 参数三:方法的参数
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                Logger logger = new Logger();
                // 前置增强
                logger.m1();

                // 执行被代理对象的方法
                Object invoke = method.invoke(clazz.newInstance(), objects);

                // 后置增强
                logger.m2();

                return invoke; // 返回方法执行的返回值
            }
        });

        // 生成代理对象并返回
        Object proxy = enhancer.create();
        return proxy;
    }
}

Spring事务

事务配置
  1. 方法上加上@Transactional(rollbackFor = Exception.class)

  2. 配置类加上@EnableTransactionManagement 和 DataSourceTransactionManager bean

@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapper;

    @Override
    // @Transactional加在方法上,当前方法开启事务,默认只回滚运行时异常
    // rollbackFor:指定回滚的异常
    // @Transactional(rollbackFor = Exception.class) :标准写法
    @Transactional(rollbackFor = Exception.class)
    public void transfer(String out, String in, Float money) throws Exception {
        // 1. 扣钱
        accountMapper.subtract(out, money);

        // 模拟异常
        // System.out.println(1/0);
        if (true){
            throw new Exception();
        }

        // 2. 加钱
        accountMapper.add(in, money);
    }
}
//配置类
@ComponentScan("com.itheima")
@EnableTransactionManagement // 开启事务管理
public class SpringConfig {
    //配置mapper位置
    @Bean
    public MapperScannerConfigurer scannerConfigurer(){
        MapperScannerConfigurer scannerConfigurer = new MapperScannerConfigurer();
        scannerConfigurer.setBasePackage("com.itheima.mapper");//设置接口包位置
        return scannerConfigurer;
    }

    //配置数据源
    @Bean
    public DruidDataSource dataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/spring");
        dataSource.setUsername("root");
        dataSource.setPassword("1234");
        return dataSource;
    }

    //配置SqlSessionFactory
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DruidDataSource dataSource){
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);//设置数据源
        return sqlSessionFactoryBean;
    }

    // 把数据库事务管理器加入IOC容器
    @Bean
    public DataSourceTransactionManager transactionManager(DruidDataSource dataSource){
        DataSourceTransactionManager manager = new DataSourceTransactionManager();
        manager.setDataSource(dataSource);
        return manager;
    }
}

SpringMVC

SpringMCV注解总结

分如下两档

永远的神

  • @RestController

    写在类上,@RestController = @Controller + @ResponseBody

  • @GetMapping

    Get请求URL

  • @PostMapping

    Post请求URL

  • @RequestParam

    1.参数映射

    2.参数设置默认值

有时用到

  • @Controller

  • @RequestMapping

  • @PutMapping

  • @DeleteMapping

  • @PathVariable

  • @ResponseBody

  • @DateTimeFormat

  • @RestControllerAdvice

  • @ExceptionHandler

  • // web层IOC注入注解 @Controller

    // 请求路径方式一: @RequestMapping

    // 请求路径方式二: Restful 四兄弟 @PostMapping @PutMapping @GetMapping @DeleteMapping

    // 返回json格式数据 @ResponseBody

    // 接收json格式参数 @RequestBody

    // 1.参数映射 2.参数设置默认值 @RequestParam

    // 设置日期格式 @DateTimeFormat

    // 写在类上,@RestController = @Controller + @ResponseBody @RestController

    // 通过请求路径直接传递参数 @PathVariable

    // 标注在类上,声明当前类是一个用于专门处理异常的类 @RestControllerAdvice

    // 标注在方法上,声明当前方法可以处理哪些异常 @ExceptionHandler

//@Controller //将当前类的对象放入容器
//@ResponseBody //将方法的返回值(对象和集合)转json返回
@RestController
//@RequestMapping("/user") 如果@RequestMapping标注在类上, 代表提取公共请求路径
public class UserController {


    @RequestMapping("/user/demo1") // 给当前方法绑定一个请求地址
    //@ResponseBody //将方法的返回值(对象和集合)转json返回
    public User demo1(String name, Integer age) {

        User user = new User(name, age);

        return user;
    }

    // value: 等同于path, 用于给当前方法绑定请求路径
    //       支持数组的写法, 代表可以为一个方法绑定多个请求路径
    @RequestMapping(value = {"/user/demo2", "/user/demo3"})
    //@ResponseBody
    public String demo2() {
        return "ok";
    }

    // method: 限制请求类型,支持数组的写法, 代表可以同时允许多种请求方式
    //        如果method属性省略, 代表的是全部方式都可以
    @RequestMapping(value = "/user/demo4", method = {RequestMethod.GET, RequestMethod.POST})
    //@ResponseBody
    public String demo4() {
        return "ok";
    }


    // 使用简单类型接收  需要保证前端传递的参数名称跟方法的形参名称一致
    // 对于一些简单类型的数据, mvc底层是可以自动完成转换的
    @RequestMapping("/user/demo5")
    public String demo5(String name, Integer age) {
        System.out.println("name:" + name + ",age:" + age);

        return "ok";
    }

    // 使用对象类型接收 需要保证前端传递的参数名称跟对象属性名称一致
    @RequestMapping("/user/demo6")
    public String demo6(User user) {
        System.out.println(user);

        return "ok";
    }


    // 使用数组类型接收  需要保证前端传递的参数名称跟方法的形参名称一致
    @RequestMapping("/user/demo7")
    public String demo7(String[] hobby) {
        System.out.println(Arrays.toString(hobby));

        return "ok";
    }


    // 使用集合类型接收  需要保证前端传递的参数名称跟方法的形参名称一致
    // 如果直接使用List来接收请求参数, 需要在参数类型之前加入@RequestParam
    @RequestMapping("/user/demo8")
    public String demo8(@RequestParam("hobby") List<String> hobby) {
        System.out.println(Arrays.toString(hobby.toArray()));

        return "ok";
    }

    // 使用日期类型接收
    // 在参数之前,使用@DateTimeFormat(pattern = "自定义日期格式")
    @RequestMapping("/user/demo9")
    public String demo9(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date updateTime) {
        System.out.println(updateTime);

        return "ok";
    }


    // 接收请求体中的json数据
    // 在方法形参中去声明一个对象, 在对象之前使用@RequestBody注解
    // 此注解就会从请求体中接收json字符串, 并且按照给的类型进行转换
//    @RequestMapping("/user/demo10")
//    public String demo10(@RequestBody User user) {
//        System.out.println(user);
//
//        return "ok";
//    }

    @RequestMapping("/user/demo10")
    public String demo10(@RequestBody Map<String, Object> map) {
        System.out.println(map.get("name"));
        System.out.println(map.get("age"));

        return "ok";
    }


    // 接收请求路径中的参数
    //@PathVariable("name") 从请求路径上获取参数   注意: 路径上使用{}做占位符
    @RequestMapping("/user/demo11/name/{name}/age/{age}")
    public String demo11(
            @PathVariable("name") String name,
            @PathVariable("age") Integer age
    ) {
        System.out.println("name:" + name + ",age:" + age);

        return "ok";
    }

    //@RequestParam 有3个使用场景
    // 1. 当请求中参数名称跟方法形参名称不对应的时候,可以使用此注解的name属性完成映射
    // 2. 当请求中有可能不传递的参数时, 可以使用此注解的defaultValue属性设置默认值
    // 3. 接收List集合

    // 注意:@RequestParam标注的参数默认情况下不能为空, 如果想取消这个限制,使用required = false
    @RequestMapping("/user/demo12")
    public String demo12(
            @RequestParam(name = "name", required = false) String username,
            @RequestParam(defaultValue = "18") Integer age
    ) {
        System.out.println("username:" + username);
        System.out.println("age:" + age);

        return "ok";
    }


    // 模拟异常
    @RequestMapping("/user/demo21")
    public void demo21(Integer type) {
        if (type == 1) {   // ArithmeticException
            int i = 1 / 0;
        } else if (type == 2) { // NullPointerException
            String s = null;
            System.out.println(s.length());
        } else { // ArrayIndexOutOfBoundsException
            Integer[] arr = new Integer[2];
            arr[5] = 1;
        }
    }

    // restful--添加
    //@RequestMapping(value = "/users", method = RequestMethod.POST)
    @PostMapping("/users")  // 仅仅接收post请求
    public void save(@RequestBody User user) {
        System.out.println(user);
    }

    // restful--查询列表
    //@RequestMapping(value = "/users", method = RequestMethod.GET)
    @GetMapping("/users")  // 仅仅接收get请求
    public List<User> findAll() {
        List<User> list = new ArrayList<>();
        list.add(new User("张三", 18));
        list.add(new User("李四", 19));
        return list;
    }

    // 主键删除
    @DeleteMapping("/users/{id}")
    public void deleteById(@PathVariable("id") Integer id) {
        System.out.println("删除id:" + id);
    }


    // 主键查询
    @GetMapping("/users/{id}")
    public void findById(@PathVariable("id") Integer id) {
        System.out.println("查询id:" + id);
    }
}

SpringBoot

启动类

// 启动类,位置必须高于其他类
@SpringBootApplication // 启动类注解
@MapperScan("com.itheima.mapper") // 指定mapper接口所在的包
@EnableAspectJAutoProxy // 开启aop
@ServletComponentScan
public class SpringBootDemoApplication {

    // springboot内置了tomcat,端口号默认8080 (约定大于配置)
    public static void main(String[] args) {
        // 固定写法
        // 参数一:启动类.class
        // 参数二:args
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }
}

yml样例

# 大小写敏感
# 缩进表示层级关系
# 参数值和冒号一定要有空格
# #代表注释
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springboot
    username: root
    password: 1234

mybatis:
  configuration:
    #    开启驼峰映射
    map-underscore-to-camel-case: true



# 日志级别( debug info warn error )
logging:
  level:
    com.itheima: info
  file:
    name: D:\\spring.log

# 只允许本地IP访问
server:
  address: 127.0.0.1

读取配置

# 大小写敏感
# 缩进表示层级关系
# 参数值和冒号一定要有空格
# #代表注释
server:
  port: 8081
  servlet:
    context-path: /itheima

# 对象:键值对的集合
user:
  username: '张三'
  password: '123456'
  addressList: # 数组:固定写法
    - '杭州'
    - '北京'
    - '上海'
读取配置一
@RestController
public class IndexController {

     // @Value("${配置路径}"):读取配置
     @Value("${user.username}")
    private String username;
    @Value("${user.password}")
     private String password;

    @GetMapping("/index")
    public String index() {


        return "hello spring boot";
    }

}
读取配置二
@Data
@Configuration // 配置类
@ConfigurationProperties(prefix = "user") // 读取配置文件中指定配置
public class UserConfig {
    private String username;
    private String password;
    private List<String> addressList;
}
@RestController
public class IndexController {

    @Autowired
    private UserConfig userConfig;

    @GetMapping("/index")
    public String index() {
        System.out.println(userConfig);

        return "hello spring boot";
    }

}

springboot增删改查

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Long id;
    private String number;
    private String userName;
    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "Asia/Shanghai")
    private Date birthday;
    private String address;
}
@Repository
public interface StudentMapper {


    @Select("select id,number,user_name,birthday,address from tb_student")
    List<Student> findAll();


    @Delete("delete from tb_student where id=#{id}")
    void deleteById(@Param("id") Long id);


    @Select("select id,number,user_name,birthday,address from tb_student where " +
            "id =#{id}")
    Student findById(@Param("id") Long id);

    @Update("update tb_student set number = #{student.number},user_name=#{student.userName},birthday=#{student.birthday},address=#{student.address} where id=#{student.id}")
    void updateById(@Param("student") Student student);

    @Insert("insert into tb_student values (#{student.id},#{student.number},#{student.userName},#{student.birthday},#{student.address})")
    void save(@Param("student") Student student);
}
public interface StudentService {
        List<Student>findAll();

        void deleteById(Long id);

        Student findById(Long id);

        void updateById(Student student);

        void save(Student student);

}
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentMapper studentMapper;

    @Override
    public List<Student> findAll() {
        return studentMapper.findAll();
    }

    @Override
    public void deleteById(Long id) {
        studentMapper.deleteById(id);
    }

    @Override
    public Student findById(Long id) {
        return studentMapper.findById(id);
    }

    @Override
    public void updateById(Student student) {
        studentMapper.updateById(student);
    }

    @Override
    public void save(Student student) {
        studentMapper.save(student);
    }

}
@RestController
public class StudnetContrroller {

    @Autowired
    private StudentService studentService;

    @GetMapping("/student")
    public Result findAll() {
        List<Student> students = studentService.findAll();
        return Result.success(students);
    }

    @DeleteMapping("/student/{id}")
    public Result deleteById(@PathVariable("id") Long id){
        studentService.deleteById(id);
        return Result.success();
    }

    @GetMapping("/student/{id}")
    public Result findById(@PathVariable("id") Long id){
        Student student = studentService.findById(id);
        return Result.success(student);
    }

    @PutMapping("/student")
    public Result updateById(@RequestBody Student student){
        studentService.updateById(student);
        return Result.success();
    }

    @PostMapping("/student")
    public Result add(@RequestBody Student student){
        studentService.save(student);
        return  Result.success();
    }
}

分页查询

        <!--mybatis分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.2</version>
        </dependency>
    @GetMapping("/emps")
    public Result findByPage(@RequestParam("page") Integer page,
                             @RequestParam("pageSize") Integer pageSize,
                             @RequestParam(value = "name", required = false) String name,
                             @RequestParam(value = "gender", required = false) Integer gender,
                             @RequestParam(value = "begin", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
                             @RequestParam(value = "end", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
        PageBean<Emp> pageBean = empService.findByPage(page, pageSize, name, gender, begin, end);
        return Result.success(pageBean);

    }
@Service
public class EmpServiceImpl implements EmpService {

    @Autowired
    private EmpMapper empMapper;


    @Override
    public PageBean<Emp> findByPage(Integer page, Integer pageSize,
                                    String name, Integer gender,
                                    LocalDate begin, LocalDate end) {
        // 1 设置分页参数
        PageHelper.startPage(page,pageSize);

        // 2.执行查询
        List<Emp> empList = empMapper.findList3(name, gender, begin, end);

        // 3.查询结果强转Page对象
        Page<Emp> p = (Page<Emp>) empList;

        // 4. 封装对象返回
        return new PageBean<>(p.getTotal(),p.getResult());
    }

}
@Mapper
public interface EmpMapper {

    List<Emp> findList3(@Param("name") String name,
                        @Param("gender") Integer gender,
                        @Param("begin") LocalDate begin,
                        @Param("end") LocalDate end);
  }

登录校验

        <!--Token生成与解析-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

过滤器
@Slf4j
@WebFilter("/*")
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 1. 请求和响应对象的强转
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        // 2. 获取请求uri
        // uri:/login   url: http://localhost:90/login
        String uri = request.getRequestURI();
        log.info("uri的值是: {}", uri);

        // 3. 判断请求uri是否是登录,如果是就放行
        if ("/login".equals(uri)) {
            filterChain.doFilter(request, response);
            return;
        }

        // 4. 走到这行一定不是登录,获取请求头的token (令牌)
        String token = request.getHeader("token");

        // 5. token不存在,返回前端未登录
        if (token == null || token.equals("")) {
            String json = new ObjectMapper().writeValueAsString(Result.error("NOT_LOGIN"));
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(json);
            return;
        }

        // 6. 解析token,如果解析失败,返回前端未登录
        try {
            JwtUtils.parseJWT(token);
        } catch (Exception e) {
            // 出现异常,token校验不通过,返回错误提示
            String json = new ObjectMapper().writeValueAsString(Result.error("NOT_LOGIN"));
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(json);
            return;
        }

        // 7. 放行
        filterChain.doFilter(request, response);
    }
}
// 启动类,位置必须高于其他类
@SpringBootApplication // 启动类注解
@MapperScan("com.itheima.mapper") // 指定mapper接口所在的包
@EnableAspectJAutoProxy // 开启aop
@ServletComponentScan // 开启过滤器
public class SpringBootDemoApplication {

    // springboot内置了tomcat,端口号默认8080 (约定大于配置)
    public static void main(String[] args) {
        // 固定写法
        // 参数一:启动类.class
        // 参数二:args
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }
}

拦截器
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {

    @Autowired
    private Gson gson;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 请求头中拿令牌
        String token = request.getHeader("token");

        // 如果字符串没有长度(null 或 空串),返回登录错误
        // org.springframework.util.StringUtils
        if (!StringUtils.hasLength(token)){
            String json = gson.toJson(Result.error("NOT_LOGIN"));
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(json); // 返回浏览器错误提示
            return false;
        }

        try {
            JwtUtils.parseJWT(token);
        } catch (Exception e) {
            String json = gson.toJson(Result.error("NOT_LOGIN"));
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(json); // 返回浏览器错误提示
            return false; // 禁止通行
        }

        // 放行
        return true;
    }
}
@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Autowired
    private LoginCheckInterceptor loginCheckInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginCheckInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/login");
    }
}

日志记录

        <!--添加依赖-->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>

        <!--aop-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
@Retention(RetentionPolicy.RUNTIME) // 保留到运行阶段
@Target({ElementType.METHOD}) // 只能加方法上
public @interface LogAnno {
    String methodDesc() default ""; // 方法用途
}
    // 查询员工
    @GetMapping("/emps/{id}")
    @LogAnno(methodDesc = "查询员工")
    public Result findById(@PathVariable("id") Integer id) {
        Emp emp = empService.findById(id);
        return Result.success(emp);
    }

    // 修改员工
    @PutMapping("/emps")
    @LogAnno(methodDesc = "修改员工")
    public Result update(@RequestBody Emp emp) {
        empService.update(emp);
        return Result.success();
    }

    // 新增员工
    @PostMapping("/emps")
    @LogAnno(methodDesc = "新增员工")
    public Result save(@RequestBody Emp emp) {
        empService.save(emp);
        return Result.success();
    }
// 记录日志的切面
@Aspect
@Component
public class LogAspect {
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private OperateLogMapper operateLogMapper;

    // 切点 (标注LogAnno注解的方法都被切中)
    @Pointcut("@annotation(com.itheima.anno.LogAnno)")
    public void pt() {
    }

    // 环绕通知
    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        OperateLog operateLog = new OperateLog();
        // 获取类名
        operateLog.setClassName(pjp.getTarget().getClass().getName());
        // 获取方法参数
        operateLog.setMethodParams(Arrays.toString(pjp.getArgs()));

        // org.aspectj.lang.reflect.MethodSignature
        MethodSignature ms = (MethodSignature) pjp.getSignature();
        // 获取方法名
        operateLog.setMethodName(ms.getMethod().getName());

        LogAnno logAnno = ms.getMethod().getAnnotation(LogAnno.class);
        // 获取方法描述
        operateLog.setMethodDesc(logAnno.methodDesc());

        String token = request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(token);
        // 拿到用户id
        Integer id = claims.get("id", Integer.class);
        operateLog.setOperateUser(id);
        // 操作时间
        operateLog.setOperateTime(LocalDateTime.now());

        long begin = System.currentTimeMillis();
        Object object = pjp.proceed();
        long end = System.currentTimeMillis();
        // 方法执行时间
        operateLog.setCostTime(end - begin);
        // 方法返回信息
        operateLog.setReturnValue(object.toString());

        // 落库
        operateLogMapper.insert(operateLog);
        return object;
    }
}

图片上传

        <!--阿里云-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.10.2</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.0.6</version>
        </dependency>
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/tlias
    username: root
    password: 1234

  servlet:
    multipart:
      max-file-size: 10MB # 单个文件默认最大1MB
      max-request-size: 100MB # 一次多个文件默认最大10MB


mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true


aliyun:
  oss:
    endpoint: oss-cn-beijing.aliyuncs.com
    accessKeyId: LTAI5tQ823aWxiqK2BmKxyeN
    accessKeySecret: 0CYrcWVlpnNJdm7Zn1R53iyEcXbGbM
    bucketName: tlias-web-management-yn
    url: https://tlias-web-management-yn.oss-cn-beijing.aliyuncs.com
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss") // 读取配置信息
public class OssProperties {
    // 服务器区域
    private String endpoint;
    // 秘钥key
    private String accessKeyId;
    // 秘钥
    private String accessKeySecret;
    // 存储空间
    private String bucketName;
    // 访问域名
    private String url;
}
//阿里存储工具类
@Component
public class OssTemplate {

    //注入配置参数实体类对象
    @Autowired
    private OssProperties ossProperties;

    //文件上传
    public String upload(String fileName, InputStream inputStream) {

        //创建客户端
        OSS ossClient = new OSSClientBuilder().build(ossProperties.getEndpoint(),
                ossProperties.getAccessKeyId(), ossProperties.getAccessKeySecret());

        //设置文件最终的路径和名称
        String objectName = "images/" + new SimpleDateFormat("yyyy/MM/dd").format(new Date())
                + "/" + System.currentTimeMillis() + fileName.substring(fileName.lastIndexOf("."));

        //meta设置请求头,解决访问图片地址直接下载
        ObjectMetadata meta = new ObjectMetadata();
        meta.setContentType(getContentType(fileName.substring(fileName.lastIndexOf("."))));

        //上传
        ossClient.putObject(ossProperties.getBucketName(), objectName, inputStream, meta);

        //关闭客户端
        ossClient.shutdown();

        return ossProperties.getUrl() + "/" + objectName;
    }

    //文件后缀处理
    private String getContentType(String FilenameExtension) {
        if (FilenameExtension.equalsIgnoreCase(".bmp")) {
            return "image/bmp";
        }
        if (FilenameExtension.equalsIgnoreCase(".gif")) {
            return "image/gif";
        }
        if (FilenameExtension.equalsIgnoreCase(".jpeg") ||
                FilenameExtension.equalsIgnoreCase(".jpg") ||
                FilenameExtension.equalsIgnoreCase(".png")) {
            return "image/jpg";
        }
        return "image/jpg";
    }
}
@RestController
public class FileController {
    @Autowired
    private OssTemplate ossTemplate;

    // 文件上传
    @PostMapping("/upload")
    public Result uploadFile(MultipartFile image) throws IOException {
        // 调用阿里云工具类上传文件
        String filePath = ossTemplate.upload(image.getOriginalFilename(), image.getInputStream());
        // 返回文件路径
        return Result.success(filePath);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值