Springboot(编程不良人)

文章目录

  • Springboot(编程不良人)
    • 1、SpringbootApplication注解相关说明
    • 2、配置文件拆分以及加载外部配置文件
    • 3、管理对象的创建
      • 3.1、创建单个对象
      • 3.2、创建多个对象
    • 4、属性注入
      • 1、@Value注解进行属性注入
      • 2、以对象的形式注入
    • 5、整合mybatis思路分析
      • 5.1、回顾spring框架如何整合mybatis
      • 5.2、springboot框架如何整合mybatis
    • 6、@Mapper注解和@MapperScan接口的区别
    • 7、本地测试
      • 7.1、spring中的本地测试
      • 7.2、Springboot框架中完成本地测试
    • 8、日志处理
      • 8.1、日志的级别
      • 8.2、日志的配置
    • 9、ems-jsp简单入门案例
      • 9.1、项目开发流程
      • 9.2、项目实例
        • 9.2.1、准备部分+环境搭建
        • 9.2.2、注册部分知识点
        • 9.2.3、登录部分知识点
        • 9.2.4、员工列表部分
        • 9.2.5、添加员工部分
        • 9.2.6、更新员工部分
    • 10、面向切面编程AOP
      • 10.1、spring框架的AOP回顾
      • 10.2、springboot框架AOP
      • 10.3、注解内的表达式
        • 10.3.1、方法级别:
        • 10.3.2、包级别:
        • 10.3.2、注解级别:
    • 11、文件上传
      • 11.1、Springboot上传文件要点
    • 12、文件下载
      • 12.1、文件下载的步骤
      • 12.2、文件下载的步骤
    • 13、拦截器
      • 13.1、过滤器的介绍
      • 13.2、拦截器的作用
      • 13.3、拦截器的特性
      • 13.4、用法介绍
      • 13.5、例子
    • 14、springboot部署方式
      • 14.1、war部署
      • 14.2、jar包部署(一般前后端分离项目)
    • 15、Restful API
      • 15.1、使用restful操作资源
      • 15.2、Restful风格测试
      • 15.3、restful标准返回类型和状态码
    • 16、异常处理
      • 16.1、传统web项目的异常处理
      • 16.2、前后端分离项目的异常处理
    • 17、CORS

1、SpringbootApplication注解相关说明

该注解是一个只能作用在类上组合注解(由@SpringBootConfiguration和@EnableAutoConfiguration和@ComponentScan)

其中@Target(指定注解作用范围)、@Retention(指定注解什么时候有效)、@Doucumented、@Inherited四个注解为java自带的元注解:只能修饰注解的注解。

  • @SpringBootConfiguration:这个注解就是用来自动配置spring、springmvc(初始化servlet。。。)相关环境

  • @EnableAutoConfiguration:开启自动配置,自动配置spring相关环境,引入第三方技术自动配置环境(mybatis-springboot、redis-springboot等第三方技术)

  • ComponentScan:组件扫描 根据注解发挥注解作用,默认扫描当前包以及其子包

2、配置文件拆分以及加载外部配置文件

平时我们的生产环境配置和开发环境配置一般不同,如何在springboot的配置文件中更换不同环境的配置文件

方法一

1、通过application-XXX.yml命名作为其他环境配置

2、在application.yml中更换配置环境

测试

1.通过application.yml进行公共配置

2.创建开发环境application-dev.yml

3.创建开发环境application-prod.yml

3.在application.yml设置开启的环境配置

4、访问hello请求

方法二 调用外部的配置文件

修改启动程序的参数

–spring.config.location=外部配置文件的绝对地址

3、管理对象的创建

3.1、创建单个对象

在springboot中管理单个对象课直接使用spring框架中注解形式创建

  • @Component 通过注解创建对象

    • Controller 用来创建控制器对象
    • Service 用来创建业务层对象
    • Repository 用来创建Dao层对象
      • 以上注解都有value属性,value属性用来指定工厂终对象的名称

例子:

1、service包中的DemoService接口

public interface DemoService {public void Demo();
}

2.service包中的DemoServiceImpl类

@Service
public class DemoServiceImpl implements DemoService{@Overridepublic void Demo() {System.out.println("Demo()方法");}
}

3、controller包中的DemoController

@RestController
public class DemoController {@Autowiredprivate DemoService demoService;@RequestMapping("/demo")public String demo(){demoService.Demo();return "demo ok";}
}

3.2、创建多个对象

如何在springboot中像spring框架一样通过xml创建对个对象,在springboot中也提供了相同的注解,如:

@Configuration、@Bean

  • @Configuration:代表这是一个spring的配置类,相当于spring.xml配置文件
  • @Bean:用来在工厂中创建这个@Bean注解表示对象
    • 默认使用@Bean创建对象在工厂中唯一标识为方法名称
    • 修改在工厂中对象标识可以使用@Bean(“工程中的名字”)指定一个名字

例子:

1.在config包下创建BeanConfig类

@Configuration//注解表名这是一个配置类,相当于spring中的spring.xml
public class BeanConfig {@Bean//注入Calendar类型的对象,名字与方法名相同public Calendar calendar(){return Calendar.getInstance();}
}

2、controller层测试

@RestController
public class DemoController {@Autowiredprivate DemoService demoServiceImpl;@Autowiredprivate Calendar calendar;@RequestMapping("/demo")public String demo(){demoServiceImpl.Demo();System.out.println("日期:"+calendar.getTime());return "demo ok";}
}

4、属性注入

1、@Value注解进行属性注入

引用类型:@Autowried

8中基本类型,String,数组、list、map

例子:

1、appliacation.yml

name: 小莫
age: 21
birthday: 2000/12/12 12:12:12 #java中默认的日期格式是:yyyy/mm/dd HH:MM:ss
sex: false
qqs: 1,2,3,4 #注入数组时,多个元素用','隔开
lists: morant,more,lirmood #注入list时,多个元素用,隔开,和数组一样
maps: "{'name':'morant','age':'21'}" #json字符串的形式

2、injectController

@RestController
public class injectController {@Value("${name}")private String name;@Value("${age}")private int age;@Value("${birthday}")private Date birthday;@Value("${sex}")private boolean sex;@Value("${qqs}")private int[] qqs;@Value("${lists}")private List<String> lists;@Value("#{${maps}}")//在注入map集合时,配置文件要是用json格式赋值 在注入式必须使用@{#{${}}}进行注入private Map<String,String> maps;@RequestMapping("/inject")public String inject(){System.out.println("name = " + name);System.out.println("age = " + age);System.out.println("birthday = " + birthday);System.out.println("sex = " + sex);System.out.println("=================");System.out.println("数组遍历");for (int qq : qqs) {System.out.println("qq = " + qq);}System.out.println("=================");System.out.println("list遍历");lists.forEach(li-> System.out.println("li = " + li));System.out.println("=================");System.out.println("map遍历");maps.forEach((key,value)-> System.out.println("key = " + key+" value = "+ value));return "inject ok";}
}

2、以对象的形式注入

@ConfigurationProperties:

/**
*作用范围:作用在类上
* 作用:用来指定配置文件中前缀的属性 注入到当前对象中属性一致的属性中
* 注意:必须要有get和set方法
*/

例子:

1、application.yml文件

order:id: 19100116age: 21

2、inject2Controller(一定要有get和set方法,一定要是用@ConfigurationProperties注解)

@RestController
/*** 作用范围:作用在类上* 作用:用来指定配置文件中前缀的属性 注入到当前对象中属性一致的属性中* 注意:必须要有get和set方法*/@ConfigurationProperties(prefix = "order")
public class inject2Controller {private String id;private String age;@RequestMapping("/inject2")public String inject2(){System.out.println(id);System.out.println(age);return "inject2 OK";}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}
}

5、整合mybatis思路分析

5.1、回顾spring框架如何整合mybatis

1.引入依赖

  • spring相关
  • mysql相关 驱动 数据源
  • mybatis相关 mybatis核心jar mybatis和spring框架整合

2。spring.xml

  • 开启注解扫描
  • 创建数据源对象
    • 注入 指定使用哪种数据源类型 注入diverClassName 注入url、username、password
  • 创建sqlSessionFactory
    • 注入 数据源 注入mapper配置文件位置 注入实体别名包
  • 创建Dao对象
    • 注入SqlSessionFactory 以及Dao接口所在包
  • 创建事务管理器 DataSourceTranacationManager
    • 注入数据源对象
  • 在业务层组件上加入事务注解 @Transacational

3.测试

5.2、springboot框架如何整合mybatis

1.引入依赖

  • spring-web
  • mysql相关 mysql驱动 druid数据源
  • mybatis相关(mybatis-spring-boot-stater)依赖

2.书写配置

  • 开启注解扫描 @SpringBootApplication @ComponentScan可以省略
  • 创建数据源
    • 注定数据源类型
    • 指定数据库驱动
    • 指定url
    • 指定username
    • 指定password
  • 创建SqlSessionFactory
    • 指定mapper配置文件的位置
    • 指定实体所在的包的位置 起别名
  • 创建Dao
    • 指定Dao接口所在的包

3.测试

例子

1、导入依赖

      <!--导入数据源 druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.4</version></dependency><!--导入数据库驱动 mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.25</version></dependency><!--导入mybatis-springboot-starter 包含mybatis和mybatis-spring--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.4</version></dependency>

2、修改配置文件 application-yml

server:port: 8989servlet:context-path: /springboot-mybatis
#整合mybatis相关配置
spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverpassword: 123456username: rooturl: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
#mybatis相关配置设置之后 才会创建SqlSessionFcatory
mybatis:type-aliases-package: com.morant.entity #指定实体类的包名,默认别名:类名或者类名的首字母小写mapper-locations: classpath:com/morant/mapper/*.xml #指定mapper配置文件的位置#在主类中指定dao接口所在的包

3、在主类中指定dao接口所在的包

@SpringBootApplication
@MapperScan("com.morant.dao")//修饰范围:用在类上 作用:用来扫描dao接口所在的包 同时将所有dao接口在工厂中创建代理对象
public class SpringBootMybatisApplication {public static void main(String[] args) {SpringApplication.run(SpringBootMybatisApplication.class, args);}}

4、测试

4.1、创建数据库

4.2、创建实体类User

public class User {private int id;private String name;private String password;public User(int id, String name, String password) {this.id = id;this.name = name;this.password = password;}public User() {}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}

4.3、创建Userdao接口

public interface UserDao {public List<User> findall();
}

4.4、在创建UserDaoMapper配置文件

<?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.morant.dao.UserDao"><select id="findall" resultType="user">select id,name,password from `user`</select></mapper>

4.5、创建UserService接口

public interface UserService {public List<User> findall();
}

4.6、创建UserServiceImpl实现类

@Service
@Transactional
public class UserServiceImpl implements UserService{private UserDao userDao;@Autowiredpublic UserServiceImpl(UserDao userDao) {//这里报错没关系,因为Dao还没被主类扫描进来,或者在Dao上加@Mapperthis.userDao = userDao;}public List<User> findall(){return userDao.findall();};
}

4.7创建UserController

6、@Mapper注解和@MapperScan接口的区别

@Mapper:添加在Dao接口上,在工厂中创建代理对象,但是一次只能作用一个Dao接口,相对麻烦

7、本地测试

7.1、spring中的本地测试

1、启动工厂

ApplicationCpntext context = new ClassPathXmlApplicationContext("spring.xml")

2、从工厂中获得指定对象

UserDao userDao = context.getBean("UserDao")

3、调用方法

useDao.xxx(参数)

7.2、Springboot框架中完成本地测试

1.引入结合junit和springboot的依赖

      <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
  1. 启动springboot应用才能启动工厂 注入测试对象

@SpringBootTest

​ 作用范围:在类上

​ 作用:在这个类实例化过程中启动springboot应用

8、日志处理

springboot框架集成日志logback日志

8.1、日志的级别

  • ALL:最低等级的,用于打开所有日志记录。

  • TRACE:很低的日志级别,一般不会使用。

  • DEBUG: 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。

  • INFO: 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。

  • WARN: 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示。

  • ERROR: 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。

  • FATAL: 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。

  • OFF: 最高等级的,用于关闭所有日志记录。

8.2、日志的配置

#配置日志
logging:level:root: info #全局日志com.morant.service: debug #指定包的日志file:name: run.log #输出日志文件的名字path: ./ #将日志文件生成在本项目下

调试时输出日志

@Service
@Transactional
public class UserServiceImpl implements UserService{private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);private UserDao userDao;@Autowiredpublic UserServiceImpl(UserDao userDao) {this.userDao = userDao;}public List<User> findall(){log.debug("查询完毕");return userDao.findall();};
}

注意

private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class); 这个注解

9、ems-jsp简单入门案例

9.1、项目开发流程

  • 需求分析:分析用户主要需求,提取出项目的核心功能,根据核心功能构建页面原型
  • 库表设计(概要设计):1.分析系统有哪些表,2.分析出表之间的关系,3.确定字段
  • 详细设计(流程图、伪代码):用来验证库表设计的准确性
  • 功能实现(编码):环境搭建 具体功能时间
  • 部署
  • 上线
  • 运维

9.2、项目实例

9.2.1、准备部分+环境搭建

1、创建ems-jsp的springboot项目

2、修改properties为yml,在main

下面新建一个webapp(存放jsp)

3、导入依赖

      <!-- 开启jsp解析依赖--><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId></dependency><!-- 开启springboot热部署调试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.4</version></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.25</version></dependency><!-- mybatis-spring-boot-stater--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.4</version></dependency>

3、项目配置

server:port: 8989 #指定端口servlet:context-path: /ems-jsp #指定项目名jsp:init-parameters:development: true #开启jsp模板的开发模式#配置jsp解析模板和数据库
spring:mvc:view:prefix: /suffix: .jspdatasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/mybatis?characterEncoding=UTF-8#配置mybatis
mybatis:mapper-locations: classpath:com/morant/mapper/*.xmltype-aliases-package: com.morant.entity#主入口加一个@MapperScan#配置日志的使用
logging:level:root: infocom.morant: debug #指定包日志

5、创建数据库表

9.2.2、注册部分知识点

1.验证码生成工具VarifyCodeUtils

package com.morant.utils;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Random;/*** 验证码工具类* 使用到Algerian字体,系统里没有的话需要安装字体**/
public class VerifyCodeUtils {// 字体只显示大写,去掉了1,0,i,o几个容易混淆的字符public static final String VERIFY_CODES = "23456789abcdefghgkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";private static Random random = new Random();/*** 使用系统默认字符源生成验证码** @param verifySize 验证码长度* @return*/public static String generateVerifyCode(int verifySize) {return generateVerifyCode(verifySize, VERIFY_CODES);}/*** 使用指定源生成验证码** @param verifySize 验证码长度* @param sources 验证码字符源* @return*/public static String generateVerifyCode(int verifySize, String sources) {if (sources == null || sources.length() == 0) {sources = VERIFY_CODES;}int codesLen = sources.length();Random rand = new Random(System.currentTimeMillis());StringBuilder verifyCode = new StringBuilder(verifySize);for (int i = 0; i < verifySize; i++) {verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));}return verifyCode.toString();}/*** 生成随机验证码文件,并返回验证码值** @param w* @param h* @param outputFile* @param verifySize* @return* @throws IOException*/public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException {String verifyCode = generateVerifyCode(verifySize);outputImage(w, h, outputFile, verifyCode);return verifyCode;}/*** 输出随机验证码图片流,并返回验证码值** @param w* @param h* @param os* @param verifySize* @return* @throws IOException*/public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException {String verifyCode = generateVerifyCode(verifySize);outputImage(w, h, os, verifyCode);return verifyCode;}/*** 生成指定验证码图像文件** @param w* @param h* @param outputFile* @param code* @throws IOException*/public static void outputImage(int w, int h, File outputFile, String code) throws IOException {if (outputFile == null) {return;}File dir = outputFile.getParentFile();if (!dir.exists()) {dir.mkdirs();}try {outputFile.createNewFile();FileOutputStream fos = new FileOutputStream(outputFile);outputImage(w, h, fos, code);fos.close();} catch (IOException e) {throw e;}}/*** 输出指定验证码图片流** @param w* @param h* @param os* @param code* @throws IOException*/public static void outputImage(int w, int h, OutputStream os, String code) throws IOException {int verifySize = code.length();BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);Random rand = new Random();Graphics2D g2 = image.createGraphics();g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);Color[] colors = new Color[5];//Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.YELLOW };Color[] colorSpaces = new Color[] { Color.WHITE, Color.blue, Color.GRAY, Color.RED, Color.GREEN, Color.ORANGE, Color.CYAN, Color.YELLOW };float[] fractions = new float[colors.length];for (int i = 0; i < colors.length; i++) {colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];fractions[i] = rand.nextFloat();}Arrays.sort(fractions);g2.setColor(Color.RED);// 设置边框色g2.fillRect(0, 0, w, h);Color c = getRandColor(200, 250);g2.setColor(c);// 设置背景色g2.fillRect(0, 2, w, h - 4);// 绘制干扰线Random random = new Random();//g2.setColor(getRandColor(160, 200));// 设置线条的颜色g2.setColor(getRandColor(100, 255));// 设置线条的颜色for (int i = 0; i < 20; i++) {int x = random.nextInt(w - 1);int y = random.nextInt(h - 1);int xl = random.nextInt(6) + 1;int yl = random.nextInt(12) + 1;g2.drawLine(x, y, x + xl + 40, y + yl + 20);}// 添加噪点// 噪声率float yawpRate = 0.02f;int area = (int) (yawpRate * w * h);for (int i = 0; i < area; i++) {int x = random.nextInt(w);int y = random.nextInt(h);int rgb = getRandomIntColor();image.setRGB(x, y, rgb);}
// 使图片扭曲shear(g2, w, h, c);//g2.setColor(getRandColor(100, 160));g2.setColor(getRandColor(100, 255));int fontSize = h - 4;Font font = new Font("Algerian", Font.ITALIC, fontSize);g2.setFont(font);char[] chars = code.toCharArray();for (int i = 0; i < verifySize; i++) {AffineTransform affine = new AffineTransform();affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize / 2, h / 2);g2.setTransform(affine);g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);}g2.dispose();ImageIO.write(image, "jpg", os);}private static Color getRandColor(int fc, int bc) {if (fc > 255){fc = 255;}if (bc > 255){bc = 255;}int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);}private static int getRandomIntColor() {int[] rgb = getRandomRgb();int color = 0;for (int c : rgb) {color = color << 8;color = color | c;}return color;}private static int[] getRandomRgb() {int[] rgb = new int[3];for (int i = 0; i < 3; i++) {rgb[i] = random.nextInt(255);}return rgb;}private static void shear(Graphics g, int w1, int h1, Color color) {shearX(g, w1, h1, color);shearY(g, w1, h1, color);}private static void shearX(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(2);boolean borderGap = true;int frames = 1;int phase = random.nextInt(2);for (int i = 0; i < h1; i++) {double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);g.copyArea(0, i, w1, 1, (int) d, 0);if (borderGap) {g.setColor(color);g.drawLine((int) d, i, 0, i);g.drawLine((int) d + w1, i, w1, i);}}}private static void shearY(Graphics g, int w1, int h1, Color color) {// 50int period = random.nextInt(40) + 10;boolean borderGap = true;int frames = 20;int phase = 7;for (int i = 0; i < w1; i++) {double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);g.copyArea(i, 0, 1, h1, 0, (int) d);if (borderGap) {g.setColor(color);g.drawLine(i, (int) d, i, 0);g.drawLine(i, (int) d + h1, i, h1);}}}
}

2、验证码实现Controller

 @RequestMapping("/generateImageCode")public void find(HttpSession session, HttpServletResponse response) throws IOException {//1.生成随机验证码String code = VerifyCodeUtils.generateVerifyCode(4);//2.保存随机字符串到session中session.setAttribute("code",code);//3.将随机字符串生成图片//4.通过response响应图片ServletOutputStream os = response.getOutputStream();VerifyCodeUtils.outputImage(120,60,os,code);}

3、密码加密,用java提供的DigestUtils

@Overridepublic void register(User user) {//1.根据数据库查询书否存在该用户名User userDB = userDao.findByUserName(user.getUsername());//2.如果存在 报错if(!ObjectUtils.isEmpty(userDB))throw new RuntimeException("用户名已存在");//3.如果不存在,就注册,注册前给密码加密String passwordSecret = DigestUtils.md5DigestAsHex(user.getPassword().getBytes(StandardCharsets.UTF_8));user.setPassword(passwordSecret);userDao.save(user);}

4、传回错误信息值前端,需要设置字符格式,用到URLEncoder类,需要设置UTF-8

@RequestMapping("/register")public String register(HttpSession session,User user,String code) throws UnsupportedEncodingException {log.debug("用户名{},真实姓名{},密码{},性别{},验证码{}",user.getUsername(),user.getRealname(),user.getPassword(),user.getGender(),code);String sessionCode = session.getAttribute("code").toString();//判断验证码是否正确try {if(!(sessionCode.equalsIgnoreCase(code)))throw new RuntimeException("验证码错误");//验证码正确,调用UseService接口进行注册userService.register(user);} catch (RuntimeException e) {e.printStackTrace();return "redirect:/regist.jsp?msg="+ URLEncoder.encode(e.getMessage(),"UTF-8");}return "redirect:/login.jsp";}

9.2.3、登录部分知识点

主要登录成功之后需要将账号存入session

 @RequestMapping("/login")public String login(HttpSession session,String username,String password) throws UnsupportedEncodingException {log.debug("接收到的用户名{},接受到的密码{}",username,password);try {User user = userService.login(username,password);session.setAttribute("user",user);} catch (Exception e) {e.printStackTrace();return "redirect:/login.jsp?msg="+URLEncoder.encode(e.getMessage(),"UTF-8");}return "emplist";}

9.2.4、员工列表部分

1、前端使用c标签需要导包

<!-- jstl c标签库,标准标签库-->
<dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version>
</dependency>

2、c-foreach标签的使用

<c:forEach items="${requestScope.employee}" var="employee"><tr><td>${employee.id}</td><td>${employee.name}</td><td>${employee.birthday}</td><td>${employee.salary}</td><td>${employee.gender?"男":"女"}</td><td><a href="javascript:void(0)">更新</a><a href="javascript:;">删除</a></td></tr>
</c:forEach>

3、HttpServletRequest的request和Model类型model添加属性都是添加到requestScop中。等价

@RequestMapping("/list")public String list(HttpServletRequest request, Model model){List<Employee> employee = employeeService.list();// request.setAttribute("employee",employee);// 上面的是servlet原始提供的一种存入数据到request域的方法等价于下面的方法model.addAttribute("employee",employee);return "emplist";}

4、要跳转请求使用redirect

5、前端引入的css前面的路径需要用${pageContext.request.contextPath}

    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/bootstrap.min.css">

9.2.5、添加员工部分

1、添加部分的主键自增设计 keyProperty=“id” useGeneratedKeys="true"

<insert id="add" parameterType="employee" keyProperty="id" useGeneratedKeys="true">insert into `employee` values (#{id},#{name},#{birthday},#{salary},#{gender})
</insert>

**2、默认java默认日期格式 **

java、Spring、springmvc默认的日期格式为 yyyy/MM/dd HH:mm:ss

//java spring springmvc默认的日期格式为 yyyy/MM/dd HH:mm:ss 除非用    @DateTimeFormat(pattern="")修改
@DateTimeFormat(pattern = "yyyy-MM-dd")

9.2.6、更新员工部分

1、更新员工应该先通过员工的id去查找该员工并回显(在url后面拼接id)

<a href="${pageContext.request.contextPath}/employee/detail?id=${employee.id}">更新</a>

2、根据回显的信息进行修改之后 在去数据库中修改,id也要回显

10、面向切面编程AOP

10.1、spring框架的AOP回顾

AOP:Aspect(切面) Oriented(面向) programming面向切面别称

Ascept(切面) = Advice(通知) + 切入点(prointcut)

Advice 通知:业务逻辑中一些附加操作成为通知,分为前置操作、后置操作、环绕操作

Point切入点:配置通知应用于项目中的哪些业务操作

Aspect切面=附加操作(Advice)+ 切入点(pointcut)

步骤:

1、类 implements xxAdvice接口

2、xml进行配置

<aop:config><aop:ppintcut id="pc" expression="execution(*包.类.方法名(方法参数))|within(类级别)|annotation(注解类型)"/><aop:advisor advice-ref="通知类" pointcut-ref="pc"/>
</aop:config>

10.2、springboot框架AOP

无xml配置,一切皆java配置

步骤:

1、引入aop切面编程依赖

<!-- 引入aop支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>

2、在spring醒目包中新建config(配置包)

/*** 自定义切面配置类*/
@Configuration//告诉springboot这是一个配置类
@Aspect//代表这是一个切面配置类
public class MyAspectConfig {//切面aspect=advice + pointcut@Before("execution(* com.morant.service.*.*(..))")//代表这是一个核心业务逻辑执行前的前置通知 value用来书写切入点表达式public void before(JoinPoint joinPoint){System.out.println("======调用前置通知========");System.out.println(joinPoint.getTarget());System.out.println(joinPoint.getStaticPart().getSignature().getName());}//切面aspect=advice + pointcut@After("execution(* com.morant.service.*.*(..))")//代表这是一个核心业务逻辑执行前的前置通知 value用来书写切入点表达式public void after(JoinPoint joinPoint){System.out.println("======调用后置通知======");System.out.println(joinPoint.getTarget());System.out.println(joinPoint.getStaticPart().getSignature().getName());}@Around("execution(* com.morant.service.*.*(..))")public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("======环绕放行前======");//放行Object proceed = proceedingJoinPoint.proceed();System.out.println("======环绕放行后======");return proceed;}
}

3、service包中的接口和类

public interface UserService {void show();void delete();String find();
}
@Service
public class UserServiceImpl implements UserService {@Overridepublic void show() {System.out.println("调用了Dao的show方法");}@Overridepublic void delete() {System.out.println("调用了Dao的delete方法");}@Overridepublic String find() {return "小明";}
}

总结!!!

//注解:
@Configuration:告诉springboot这是一个配置类
@Aspect:代表这是一个切面配置类
@Before("execution(* com.morant.service.*.*(..))"):代表这是一个核心业务逻辑执行前的前置通知 value用来书写切入点表达式
@After("execution(* com.morant.service.*.*(..))"):代表这是一个核心业务逻辑执行后的后置通知 value用来书写切入点表达式
@Around("execution(* com.morant.service.*.*(..))"):代表这是一个环绕同志 value用来书写切入点表达式其中
@Before
@After
这两个注解的方法中可以使用JoinPoint连接点类作为参数,可以获得业务逻辑的类名和方法名
获得类名:joinPoint.getTarget()
获得方法名:joinPoint.getStaticPart().getSignature().getName()@Around
需要proceedingJoinPoint连接点类作为参数传递
放行方法:proceedingJoinPoint.proceed() //放行之后回显调用放行后面的代码 然后在执行业务逻辑

10.3、注解内的表达式

10.3.1、方法级别:

@Before(execution(* com.morant.service.*.*(..)))

表示返回值类型随意 在com.morant.service包中的所有类的所有方法,参数随意

10.3.2、包级别:

@Before(within(com.morant.service))

表示在com.morant.service包中的所有类的所有方法

10.3.2、注解级别:

在com.morant.annotations里新建MyAdvice注解,并把注解放在serviceImpl类的方法上

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAdvice {
}

故表达式可以写成

@Before(@annotation(com.morant.annotations.MyAdvice))

11、文件上传

11.1、Springboot上传文件要点

1、前端

表单中一定要用post提交请求,类型要设置为enctype=“multipart/form-data”

2、后端

推荐用一个绝对路径上传文件,因为jar包无法访问内部路径,我们需要注入一个绝对路径

@Controller
public class UploadController {private static final Logger log = LoggerFactory.getLogger(UploadController.class);@Value("${file.upload.dir}")private String realPath;@RequestMapping("/upload")public String upload(MultipartFile file) throws IOException {log.debug("文件类型{}",file.getContentType());log.debug("文件原文件名{}",file.getOriginalFilename());//定义新的名字String originalFilename = file.getOriginalFilename();String newName = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date())+originalFilename.substring(originalFilename.lastIndexOf("."));log.debug("新文件名{}",newName);//上传文件file.transferTo(new File(realPath,newName));return "redirect:/upload.jsp";}
}

3、配置:最大下载大小

注意:

substring(int i):从字符串第i为开始一直取到最后一位

上传文件的语句 :

​ //上传文件
​ file.transferTo(new File(realPath,newName));

给文件取新的名字

​ //定义新的名字
​ String originalFilename = file.getOriginalFilename();
​ String newName = new SimpleDateFormat(“yyyyMMddHHmmssSSS”).format(new Date())+
​ originalFilename.substring(originalFilename.lastIndexOf("."));
​ log.debug(“新文件名{}”,newName);

12、文件下载

12.1、文件下载的步骤

  • 确定项目中那些资源可以被下载
  • 将可以被下载的资源放位置、文件上传服务器 fastdfs(dfs 分布式文件存储系统 多个节点 冗余备份)、上传OSS对象存储、七牛云。
  • 项目汇总开发一个下载页面

12.2、文件下载的步骤

1、创建项目

2、引入jsp依赖

<!-- 解析-jsp--><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId></dependency>

3、jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %><!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>文件下载</title>
</head>
<body>
<h1>文件下载</h1>
<a href="${pageContext.request.contextPath}/download?fileName=a.txt">a.txt</a>
<a href="${pageContext.request.contextPath}/download?fileName=HELP.md">HELP.md</a>
<a href="${pageContext.request.contextPath}/download?fileName=中文.txt">中文.txt</a>
</body>
</html>

4、配置文件设置下载地址

server:port: 8989servlet:context-path: /springboot-downloadspring:mvc:view:prefix: /suffix: .jspfile:download:dir: D:\JavaAll\SpringBoot\springboot-download\download

5、Controller

@Controller
public class downloadController {private static final Logger log = LoggerFactory.getLogger(downloadController.class);@Value("${file.download.dir}")private String realPath;@RequestMapping("/download")public void download(String fileName, HttpServletResponse response) throws IOException {log.debug("当前下载的文件名为{}",fileName);log.debug("当前下载的文件目录为");//1.去指定目录中读取文件File file = new File(realPath,fileName);//2.将文件读取为输入流FileInputStream is = new FileInputStream(file);//3.获取响应输入流之前一定要设置附件下载格式 attachment附件response.setHeader("content-disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));//4.输入流复制给输出流ServletOutputStream os = response.getOutputStream();byte [] b= new byte[1024];int len =0;while((len=(is.read(b)))!=-1){os.write(b,0,len);}//第二种复制方法//FileCopyUtils.copy(is,os);//5.释放资源is.close();}
}

注意:

1、先要把文件转换为文件输入流

2、要设置响应消息的响应头:附件下载格式以及编码格式

3、记得要关闭流

4、不许要返回值

5、下载源文件路径在yml中配置

6、Spring框架提供文件复制类FileCopyUtils 可以进行复制

13、拦截器

13.1、过滤器的介绍

filter 过滤器:过滤器可以拦截javaweb中请求,放行,中断

强大:拦截一切资源:.jsp、html、css、img …

13.2、拦截器的作用

作用:将controller中共有代码放到拦截器中执行,减少controller中代码冗余

13.3、拦截器的特性

  • 拦截器芝兰姐controller相关请求
  • 拦截器可以中断请求轨迹
  • 请求之前如果该请求配置了拦截器,请求会先经过拦截器,拦截器放行之后执行controller,controller执行完成后会回到拦截器继续执行拦截器中的代码

13.4、用法介绍

1、a.类 implements HandlerInterceptor 接口 引入默认实现

  • preHandler 预先处理方法:拦截器最先执行的按方法,范围值为布尔类型的值(true:放行,false:中断)
  • postHandler 过程中处理:controller返回之后回到postHandler这个方法执行,执行完成这个方法开始响应浏览器
  • aferCompletion 最后完成:当相应结构结束后会执行拦截器这个方法中的内容

2、配置拦截器

  • Springmvc配置方式:MVC:interceptors springmvc.xml

  • springboot提供了springmvc配置接口:WebMvcConfigurer

  • 类 implements WebMvcConfigurer{

    ​ //覆盖配置拦截器的方法

    ​ 1、使用哪个拦截器

    ​ 2、拦截器拦截的请求地址

    ​ 3、排除哪些请求

    }

13.5、例子

1、创建interceptors包 并创建两个拦截器

Interceptor1.java

package com.morant.interceptors;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*自定义拦截器*/
public class Interceptor1 implements HandlerInterceptor {private  static  final Logger  log = LoggerFactory.getLogger(Interceptor1.class);@Override//最先执行//参数3:handler 当前请求的控制器对象 DemoController/loginpublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.debug("===========1=============");//返回值为false是的重定向路径//response.sendRedirect(request.getContextPath()+"/error404.jsp");return true;}@Override//参数3:handlaer:当前控制器对象//参数4:modelAndView 模型和视图 当前请求访问的modelAndView对象public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.debug("===========2=============");}@Override//参数3:handlaer:当前控制器对象//参数4:Exception:如果控制器出现异常的对象public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.debug("===========3=============");}
}

Interceptor2.java

package com.morant.interceptors;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class Interceptor2 implements HandlerInterceptor {private  static  final Logger log = LoggerFactory.getLogger(Interceptor1.class);@Override//最先执行//参数3:handler 当前请求的控制器对象 DemoController/loginpublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.debug("===========4=============");//返回值为false是的重定向路径//response.sendRedirect(request.getContextPath()+"/error404.jsp");return true;}@Override//参数3:handlaer:当前控制器对象//参数4:modelAndView 模型和视图 当前请求访问的modelAndView对象public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.debug("===========5=============");}@Override//参数3:handlaer:当前控制器对象//参数4:Exception:如果控制器出现异常的对象public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.debug("===========6=============");}
}

2、创建config包,并配置拦截器

package com.morant.config;import com.morant.interceptors.Interceptor1;
import com.morant.interceptors.Interceptor2;
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 MvcConfig implements WebMvcConfigurer {//配置拦截器的相关方法@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new Interceptor1()).addPathPatterns("/**")//所有路径.excludePathPatterns("/file/**")//除了file下的请求.order(1);//指定优先级 有限顺序为自然数顺序registry.addInterceptor(new Interceptor2()).addPathPatterns("/**")//所有路径.excludePathPatterns("/file/**")//除了file下的请求.order(2);}
}

注意:

1.配置了两个拦截器,拦截器方法的执行顺序是栈的方式,先进入拦截器的后返回controller和最后过程

14、springboot部署方式

14.1、war部署

1、设置打包方式为war

<packaging>war</packaging>

2、去除springboot项目内嵌tomcat依赖

  <dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope></dependency>

3、在插件中指定入口类

​ 3.1.configuration标签的内容是新加入的

<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><!--配置springboot入口类--><fork>true</fork><!--增加jvm参数--><jvmArguments>-Dfile.encoding=UTF-8</jvmArguments><!--指定入口类--><mainClass>com.morant.SpringBootInterceptorApplication</mainClass></configuration></plugin></plugins>
</build>

​ 3.2 修改入口类的内容(继承类、重写方法)

@SpringBootApplication
//SpringBootServletInitialize:不在使用内嵌的容器使用 使用外部的web容器启动 外部tomcat启动
public class SpringBootInterceptorApplication extends SpringBootServletInitializer {public static void main(String[] args) {SpringApplication.run(SpringBootInterceptorApplication.class, args);}//单单继承SpringServletIntialize不行,还要重写配置方法(配置入口是谁)@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {return builder.sources(SpringBootInterceptorApplication.class);}
}

4、打包测试

注意:一旦使用war包部署,application.yml中配置的port端口和context-path失效。访问时使用war报名字和外部tomcat端口号进行访问

14.2、jar包部署(一般前后端分离项目)

1、默认是jar包打包 也可已进行设置

<packaging>jar</packaging>

2、打包,在target目录中获取对应的jar文件

3、启动jar包 java -jar 对应的文件名字 nohup &

15、Restful API

15.1、使用restful操作资源

  • [GET] :/users #查询某用户列表
  • [GET]:/users/1001 #查询某个用户信息
  • [POST]:/users #新建用户信息
  • [PUT]:users/1001 #更新用户信息(全部字段)
  • [PATCH]:/users/1001 #更新用户信息(部分字段)
  • [DELETE]:/users/1001 #删除用户信息

15.2、Restful风格测试

1、v1/controller

//@RestController:专用于restful风格 @Controller:专用于传统开发注解
@Controller
@RequestMapping("/v1/users")
public class UserController {private static final Logger  log = LoggerFactory.getLogger(UserController.class);//查询某个用户的方法@GetMapping("/{id}")@ResponseBody //将控制器方法的返回值转为jsonpublic User user(@PathVariable("id") Integer id){log.debug("id=:{}",id);return new User(id,"morant",new Date(),10000.00);}//查询所有用户的方法@GetMapping@ResponseBodypublic ArrayList<User> users(){ArrayList<User> users = new ArrayList<>();users.add(new User(1,"MORANT",new Date(),1000.00));users.add(new User(2,"MORE",new Date(),1000.00));return users;}//添加一个用户//@RequestBody将前端传来的json数据转化为对象 相当于反序列@PostMapping@ResponseBody//将后端的对象转化为json传到前端显示 相当于序列话的过程public void saveuser(@RequestBody User user){log.debug("name:{} bir:{} salary{}",user.getName(),user.getBir(),user.getSalary());}//修改一个用户的全部字段@PutMapping("/{id}")@ResponseBodypublic void updateuser(@PathVariable("id") Integer id,@RequestBody User user){log.debug("id{}",user.getId());log.debug("name:{} bir:{} salary{}",user.getName(),user.getBir(),user.getSalary());}//删除一个用户@DeleteMapping("/{id}")@ResponseBodypublic void deleteuser(@PathVariable("id")Integer id){log.debug("id:{}",id);}
}

2、使用postman测试 需要开启主类

//总结
//@RestController:专用于restful风格 @Controller:专用于传统开发注解
//@RestController= @Controller + @RequestBody
//@ResponseBody 将后端的对象转化为json传到前端显示 相当于序列话的过程
//@RequestBody将前端传来的json数据转化为对象 相当于反序列

15.3、restful标准返回类型和状态码

ResponseEntity:springmvc 封装了一个专用于restful响应类,这个类在响应时可以提供响应的状态码,同时还可以自定义响应头

HttpStatus: springmvc 封装了一个枚举类型类 这个类中的是网络中的状态码

修改Controller

    //查询某个用户的方法@GetMapping("/{id}")@ResponseBody //将控制器方法的返回值转为jsonpublic ResponseEntity<User> user(@PathVariable("id") Integer id){log.debug("id=:{}",id);return new ResponseEntity<>(new User(id,"morant",new Date(),10000.00), HttpStatus.OK);}

16、异常处理

16.1、传统web项目的异常处理

1、引入thymeleaf模板

<!-- 引入thymeleaf模板--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>

2、配置thymeleaf

server:port: 8081spring:thymeleaf:prefix: classpath:/templates/suffix: .htmlcache: false

3、编写controller/DemoConteoller(计算和登录两个报错方法)

@Controller
@RequestMapping("/demos")
public class DemoController {@RequestMapping("/demo")public String demo(){System.out.println("demo ok....");int i =1/0;return "hello";}@RequestMapping("/login")public String login(String username,String password){if("morant".equals(username)&&"123456".equals(password)){return "hello";}else{throw new UserNameNotFondException("用户名找不到");}}
}

4、自定义用户名找不到的方法(/exception/UserNameNotFondException)

package com.morant.exception;public class UserNameNotFondException extends RuntimeException{public UserNameNotFondException(String message) {super(message);}
}

5、创建exception/GlobalExceptionResolver继承HandlerExceptResolver

@Component//将该类加载进入工厂
public class GlobalExceptionResolver implements HandlerExceptionResolver {//resolveException:当前控制器中的任何一个方法发生异常时,如果该控制器的方法没有自己处理异常(try...catch),则会进入该方法//注意 在异常处理的方法中,完成自己的异常处理//参数1:当前请求对象//参数2:当前请求对应的响应头//参数3:当前出现错误的方法//参数4:出现异常的异常对象//返回值:模型和视图@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {System.out.println("这是全局异常处理");System.out.println("当前异常为"+ex);ModelAndView modelAndView = new ModelAndView();if(ex instanceof UserNameNotFondException){modelAndView.setViewName("login");return modelAndView;}modelAndView.setViewName("500");return modelAndView;}
}

总结

自定义的全局异常处理对象GlobalExceptionResolver需要使用@Component注解在spring工厂中进行注册

HandlerExceptionResolver:spring为我们提供的一个接口 作用于所有控制器报错的情况 我们只需要自己定义一个全局异常处理对象去继承该接口

16.2、前后端分离项目的异常处理

前后端的交互采用ajax的方式

1、创建 controller/DemoController类

@RestController
@RequestMapping("/demo")
public class DemoController {@GetMappingpublic ResponseEntity<String> demo(){System.out.println("demo ok");int n=1/0;return new ResponseEntity<String>("demo ok", HttpStatus.OK);}@GetMapping("{id}")public ResponseEntity<Integer> demo1(@PathVariable Integer id){System.out.println("demo ok");if (id==0) {throw new IllegalNumberException("输入非法数字");}return new ResponseEntity<Integer>(1/id, HttpStatus.OK);}
}

2、定义自定义异常(非法数字异常)

public class IllegalNumberException extends RuntimeException{public IllegalNumberException(String message) {super(message);}
}

3、创建exception/GlobalExceptionResolver类(添加@ControllerAdvice注解)

@ControllerAdvice
public class GlobalExceptionResolver {@ExceptionHandler(value = RuntimeException.class) //用在方法上public ResponseEntity<String> exceptionHandler1(Exception ex){//这个方法名随便起System.out.println("进入数字异常");return new ResponseEntity<String>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);}@ExceptionHandler(value = Exception.class) //用在方法上public ResponseEntity<String> exceptionHandler(Exception ex){//这个方法名随便起System.out.println("进入自定义异常处理");return new ResponseEntity<String>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);}
}

总结:

@ControllerAdvice:注解可以使得controller的错误在这这个类中进行处理

@ExceptionHandler(value = Exception.class) :对应controller抛出的错误类型(就近原则,没有一一对应的就找value = Exception.class)

17、CORS

1.什么是CORS

​ **定义:**跨域资源共享

2.什么是跨域资源共享

解释:语序浏览器可以从当前服务器通过ajax访问另一个源服务地址

3.同源策略

​ 是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。同源是浏览器安全的基石。

4.什么是源(orign)

​ 源【orign】就是协议、域名、端口号。例如:http://www.baiodu.com:80这个url

​ 协议:http

​ 域名:www.baidu.com

​ 端口号:80

5.哪些操作不会受到同源的限制

<script src=""/script>
<img>
<link>
<iframe>

6.那些操作会受到同源限制

​ ajax

​ 出现跨域:Acsee-Control-Allow-Orign

7.springboot中如何解决跨域问题

  • 局部:在每一个Controller中假如@CrossOrign注解
  • 全局:
package com.morant.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;@Configuration
public class CorsConfig{@Beanpublic CorsFilter corsFilter(){UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration corsConfiguration = new CorsConfiguration();corsConfiguration.addAllowedOrigin("*");//语序任何域名使用corsConfiguration.addAllowedHeader("*");//允许任何头corsConfiguration.addAllowedMethod("*");//语序任何方法(post,get等)source.registerCorsConfiguration("/**",corsConfiguration);//处理所有请求的跨域配置return new CorsFilter(source);}
}

/这个方法名随便起
System.out.println(“进入数字异常”);
return new ResponseEntity(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}

@ExceptionHandler(value = Exception.class) //用在方法上
public ResponseEntity<String> exceptionHandler(Exception ex){//这个方法名随便起System.out.println("进入自定义异常处理");return new ResponseEntity<String>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}

}


> 总结:
>
> @ControllerAdvice:注解可以使得controller的错误在这这个类中进行处理
>
>  @ExceptionHandler(value = Exception.class) :对应controller抛出的错误类型(就近原则,没有一一对应的就找value = Exception.class)## 17、CORS1.什么是CORS​    **定义:**跨域资源共享2.什么是跨域资源共享​    **解释**:语序浏览器可以从当前服务器通过ajax访问另一个源服务地址3.同源策略​  是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。同源是浏览器安全的基石。4.什么是源(orign)​   源【orign】就是协议、域名、端口号。例如:http://www.baiodu.com:80这个url​    协议:http​ 域名:www.baidu.com​    端口号:805.哪些操作不会受到同源的限制```html
<script src=""/script>
<img>
<link>
<iframe>

6.那些操作会受到同源限制

​ ajax

​ 出现跨域:Acsee-Control-Allow-Orign

7.springboot中如何解决跨域问题

  • 局部:在每一个Controller中假如@CrossOrign注解
  • 全局:
package com.morant.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;@Configuration
public class CorsConfig{@Beanpublic CorsFilter corsFilter(){UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration corsConfiguration = new CorsConfiguration();corsConfiguration.addAllowedOrigin("*");//语序任何域名使用corsConfiguration.addAllowedHeader("*");//允许任何头corsConfiguration.addAllowedMethod("*");//语序任何方法(post,get等)source.registerCorsConfiguration("/**",corsConfiguration);//处理所有请求的跨域配置return new CorsFilter(source);}
}

Springboot(编程不良人)相关推荐

  1. 【编程不良人】快速入门SpringBoot学习笔记06---RestFul、异常处理、CORS跨域、Jasypt加密

    1. RestFul 配套视频:[编程不良人]2021年SpringBoot最新最全教程_哔哩哔哩_bilibili 1.1 引言 REST全称是(Resources) Representationa ...

  2. 【编程不良人】快速入门Spring学习笔记08---事务属性、Spring整合Structs2框架(SM)、Spring整合Mybatis+Struts2(SSM)、Spring注解、SSM注解式开发

    1. 事务属性 1.1 事务传播属性 配套视频:[编程不良人]快速入门Spring,SpringBoot.SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili # ...

  3. jwt实战详解--B站编程不良人视频笔记

    文章目录 前言 一.什么是JWT 二.JWT能做什么 1.授权 2.信息交换 三.为什么使用JWT 四.JWT的结构是什么 五.使用JWT 1.引入依赖 2.生成token 3.根据令牌和签名解析数据 ...

  4. 【编程不良人】MongoDB最新实战教程学习笔记

    简介 视频链接:01.简介和历史_哔哩哔哩_bilibili 文档地址: https://docs.mongodb.com/manual/ MongoDB教程:MongoDB 教程 | 菜鸟教程 注意 ...

  5. Hadoop 从入门到精通----leo学习编程不良人视频的笔记--part01

    编程不良人原版笔记 - https://blog.csdn.net/wei198621/article/details/111280555 part 01 hadoop 集群的搭建 – https:/ ...

  6. Hadoop 从入门到精通----编程不良人笔记

    编程不良人原版笔记 - https://blog.csdn.net/wei198621/article/details/111280555 part 01 hadoop 集群的搭建 – https:/ ...

  7. 【编程不良人】SpringSecurity实战学习笔记07---授权

    配套视频:61.授权之授权核心概念_哔哩哔哩_bilibili 什么是权限管理? 权限管理核心概念 Spring Security权限管理策略 基于URL地址方式实现的权限管理 基于方法实现的权限管理 ...

  8. B站【编程不良人】Redis教程整理学习笔记(超详细拓展)

    Redis 1. NoSQL的引言 NoSQL( Not Only SQL ),意即不仅仅是SQL, 泛指非关系型的数据库.Nosql这个技术门类,早期就有人提出,发展至2009年趋势越发高涨. 2. ...

  9. Docker学习视频笔记【编程不良人】

    1.Docker介绍 2.Docker与虚拟机对比 3.Docker引擎安装 4.Docker中核心概念 5.Docker核心架构图 6.配置阿里云镜像加速 Docker 配置国内镜像源_hub-mi ...

最新文章

  1. 学习旧岛小程序 (3)组件的样式
  2. udp java 编程_JAVA 网络编程之UDP编程
  3. sql中索引不会被用到的几种情况
  4. vue进入页面执行的钩子函数_解决VUE mounted 钩子函数执行时 img 未加载导致页面布局的问题...
  5. java中finalizer终结方法学习心得
  6. Linux(debian7)操作基础(十五)之systemd下lightdm免密登录
  7. mangTomany 自关联之个人感悟
  8. 【转】Qt QTableview使用
  9. spring boot @value_spring+vue全栈开发实战-第二章Spring Boot 基础配置-笔记0302-2020
  10. centos7 里面dump_centos7使用lldb调试netcore应用转储dump文件
  11. qt最大化和还原实现_Qt 窗口操作函数(置顶、全屏,最大化最小化按钮设置等)...
  12. 编程实现二叉树的遍历
  13. 算法图解第八章笔记与习题(贪婪算法)
  14. c语言数列求和程序137,C语言循环结构 -C语言数列求和(使用while循环)
  15. 在eclipse中编写word count的Java程序打包到虚拟机中运行
  16. 多步攻击场景构建和攻击链提取方法
  17. Selenium的文件上传和操作Cookie等方法_Sinno_Song_新浪博客
  18. SQLServer2008R2安装和使用
  19. android gettext方法,android – getString()和getText()有什么区别?
  20. 从OJB到Hibernate的迁移

热门文章

  1. 物联网基础:EC20 连接阿里云进行数据收发
  2. 2022 主站及创作侧年度总结 - 相信未来、期待未来
  3. 作为一名工程师,你应该专注于成为一名多面手还是专家?
  4. mysql dml语句 先读取在更新_事务的4个特性——ACID(原子性、一致性、隔离性和持久性)、更新丢失问题...
  5. 智能手表短信读取实现具体教程(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)Version2.0改进版
  6. 计算机德育教育课题,德育教育研究课题有哪些研究方向
  7. 51单片机五层电梯控制器 基于51单片机的五层电梯控制系统
  8. Qt优秀开源项目之十二:shotcut
  9. GAN生成对抗网络合集(七):cycleGAN—循环损失的提出 / starGAN
  10. 火狐浏览器打开b站默认静音解决办法