素材巴巴 > 程序开发 >

Spring和MVC

程序开发 2023-09-03 13:00:24

SpringMVC

是Spring框架的明星产品,用来 接收浏览器发来的请求+并返回响应数据

遵循MVC思想: 主要是想要松耦合,实现代码间的高内聚, 提高代码的可维护性

M 是Model, 模型层, 用来封装数据

V 是View, 视图层, 用来展示数据

C 是Controller, 控制层 作用就是用来 接受请求和给出响应

一、工作原理(工作流程)

1, 前端控制器DispatcherServlet: 接受请求并分发请求   /dɪˈspætʃə(r)/      /ˈsɜːvlɪt/ 

2, 处理器映射器HandlerMapping: 根据请求,找到具体能处理请求的类名,方法名 

3, 处理器适配器HandlerAdapter: 正式开始调用方法处理请求,并返回结果 

4, 视图解析器ViewResolver: 把页面找到,把数据进行解析

5, 视图渲染View: 具体展示数据并返回给浏览器

二、实现前后端交互使用到的注解 

1、@GetMapping @PostMapping @DeleteMapping @PutMapping

规定浏览器的不同访问方式

2、@RequestMapping

将请求 和 处理请求的 控制器方法 关联起来,建立映射关系。SpringMVC 接收到指定的请求,就会来找到在映射关系中对应的控制器方法来处理这个请求。

@RequestMapping标识一个类:设置映射请求的请求路径的初始信息。
@RequestMapping标识一个方法:设置映射请求请求路径的具体信息。

3、@ResponseBody

作用在方法上,将该方法的返回的结果直接写入 HTTP 响应正文(ResponseBody)中。

4、@RequestBody

作用在形参列表上,用于将前台发送过来固定格式的数据【xml 格式或者 json等】封装为对应的 JavaBean 对象

5、@RestController

 @RestController注解相当于@ResponseBody + @Controller合在一起的作用

 6、get请求参数解析

(1)路径拼接形式

http://localhost:8080/car/insert?id=1&name=张三&age=18@GetMapping("/add")
 public static String add(Integer id ,String color,Integer price){return "汽车的编号为:"+id+"  "+"颜色为:"+color+"价格为:"+price;
 }

注意事项:服务器端参数类型使用包装类型,默认为null,避免客户端传入数据不赋值报错。

(2)RESTFul风格

http://localhost:8325/api/BuildingMessageManagementController/id@GetMapping("/{id}")
 public Result selectById(@PathVariable String id) {}

  7、Post/Put 参数解析

(1)浏览器传来formdata形式的参数,直接使用对象接参。

(2)浏览器惨传来json形式参数,使用@RequestBody接参。

 @PostMapping("/saveUser")
 // RequestBody属性作用:body中对象为空,就不接收解析,避免报错
 public String saveUser(@RequestBody(required = false) User user){userService.saveUser(user);return "用户入库成功!!!";
 }

(3)@PathVariable RestFul风格传参

http://localhost:8008/api/findAllWorkRecord/pageNum/pageSize
@PostMapping({"/findAllWorkRecord", "/findAllWorkRecord/{pageNum}/{pageSize}"})
 public Result findAllWorkRecord(@PathVariable(required = false) Integer pageNum, @PathVariable(required = false) Integer pageSize, @RequestBody(required = false) WorkRecord model)

访问路径为数组形式,参数携带在路径上;

路径上的参数使用@PathVariable解注解析;注解中required表示为空不接收;

(4)@RequestParam

属性:
 @RequestParam(value = "u1",required = false,defaultValue = "default") String username
 value:指定为形参赋值的请求参数的参数名
 required:设置是否必须传输此请求参数,默认值为true,如果为true没传值则400
 defaultValue:不管required属性值为true或false,当value所指定的请求参数没有传输或传输的值为""时则使用默认值为形参赋值@RequestMapping(value = "/method02")public String method02(@RequestParam("name") String name,@RequestParam("age") Integer age,@RequestParam(value = "money", required = false) Double mon) {User user = new User();user.setName(name);user.setAge(age);user.setMoney(mon);return JSON.toJSONString(user);}
 

Spring框架

Spring中万物皆Bean,IoC和DI是Spring框架两大核心

一、IoC

IoC(Inversion of Control)控制反转,就是将对象创建的权力及对象的生命周期的管理交由Spring框架来处理。

1、 IoC底层原理

spring认为万物皆是bean,配置bean的位置,spring自动完成ioc

IOC底层是Map结构,Map

数据结类似: {"hello",new Hello()}

spring不能new一个对象,只能用反射创建对象,所以底层类似:

{"hello",Class.forName("cn.tedu.spring.Hello").newInstance() }

2、Spring中将类声明为Bean的注解

@Componnet
用于普通组件,定位不明

@Repository
一般用于持久层DAO,数据库交互

@Service
一般用于服务层Service,封装服务

@Controller
一般用于控制层Controller,用于与前端交互

四者使用没有区别,区别在于定位,后三者为Spring预留,后期可能会进行功能增强。当被扫描的不同的两个包中类名相同,可以给@Component注解加值@Component(value=“p1”)。启动类自动扫描本包及子包,所以启动类要在所有文件之上。

@Configuration:配置类

二、DI

自身对象中的内置对象是通过注入的方式进行创建。

public class Order {@Autowired  User user;
 }

三、AOP面向切面编程

切面本质为一个类,包含切点和通知,通知和切点本质为一个方法

1、五种切入方式

  1. 前置通知Before
  2. 后置通知After
  3. 环绕通知Around
  4. 返回后通知AfterReturning
  5. 异常通知AfterThrowing。后两者不可能同时执行

2、切面入门使用

添加APO依赖

org.springframework.bootspring-boot-starter-aop
 

定义切面,类上添加注解@Component @Aspect 

定义切点(添加Pointcut注解的方法)

定义通知(添加Before注解的方法)

@Component
 @Aspect
 public class AopPojo {/** Pointcut* 作用:该注解表示是哪个路径里面方法触发* 参数列表:cn.tedu.service是包路径。 *表示1个  ..表示多个。 *依次代表方法返回值类型,类名,方法名,(..)是参数列表,都可具体到类和方法** 使用方法二: 注解里面的值为定义注解的路径* @Pointcut("@annotation(com.jt.resource.annotation.RequiredLog)")* */@Pointcut("execution(* com.hssmart.controller.*.*(..))")public void beforeText(){}   //方法体为空,此方法中不需要写任何内容,只负责承载@Pointcut注解@Before("beforeText()")public void beforeMethod() {System.out.println("哈哈哈");}
 }

3、环绕例子

    @Around("beforeText()")public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable {String methodName = pjp.getSignature().getName();// 得到参数数组Object[] args = pjp.getArgs();for (Object arg : args) {// 获取参数列表中HttpServletRequest对象,然后获取token值if (arg instanceof ShiroHttpServletRequest) {HttpServletRequest httpServletRequest = (HttpServletRequest) arg;System.out.println(httpServletRequest.getHeader("token"));}}//@BeforeSystem.out.println("【环绕前置通知】---"+ methodName +"---【方法开始】");//就是利用反射调用目标方法即可,就是 method.invoke(obj, args) 得到的proceed是目标方法的返回值Object proceed = pjp.proceed(args);//@AfterReturningSystem.out.println("【环绕返回通知】---"+ methodName +"---【方法返回,返回值 "+ proceed +"】");//反射调用后的返回值也一定返回出去,不返回会空指针return proceed;}

注意事项:通知返回值为Object,参数是被环绕方法的具体路径。

四、spring提供的注解

1.声明bean的注解

@Component 组件,通用的注解方式

@Service 在业务逻辑层使用(service层)

@Repository 在数据访问层使用(dao层)

@Controller 在表现层使用,控制器的声明(C)

@Configuration:配置类

2.注入bean的注解

@Autowired:由Spring提供

@Inject:由JSR-330提供

@Resource:由JSR-250提供

都可以注解在set方法和属性上,推荐注解在属性上(一目了然,少写代码)。

3.java配置类相关注解

@Configuration 声明当前类为配置类,相当于xml形式的Spring配置(类上)

@Bean 注解在方法上,声明当前方法的返回值为一个bean,替代xml中的方式(方法上)

@Configuration 声明当前类为配置类,其中内部组合了@Component注解,表明这个类是一个bean(类上)

@ComponentScan 用于对Component进行扫描,相当于xml中的(类上)

@WishlyConfiguration 为@Configuration与@ComponentScan的组合注解,可以替代这两个注解

4.切面(AOP)相关注解

Spring支持AspectJ的注解式切面编程。

@Aspect 声明一个切面(类上)

使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。

@After 在方法执行之后执行(方法上) @Before 在方法执行之前执行(方法上) @Around 在方法执行之前与之后执行(方法上)

@PointCut 声明切点

在java配置类中使用@EnableAspectJAutoProxy注解开启Spring对AspectJ代理的支持(类上)

5.@Bean的属性支持

@Scope 设置Spring容器如何新建Bean实例(方法上,得有@Bean)

其设置类型包括:

· Singleton (单例,一个Spring容器中只有一个bean实例,默认模式),

· Protetype (每次调用新建一个bean),

· Request (web项目中,给每个http request新建一个bean),

· Session (web项目中,给每个http session新建一个bean),

· GlobalSession(给每一个 global http session新建一个Bean实例)

@StepScope 在Spring Batch中还有涉及

@PostConstruct 由JSR-250提供,在构造函数执行完之后执行,等价于xml配置文件中bean的initMethod

@PreDestory 由JSR-250提供,在Bean销毁之前执行,等价于xml配置文件中bean的destroyMethod
@Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean。

6、@CrossOrigin 跨域

五、aop实现日志打印

  1. 添加依赖

    在 pom.xml 文件中添加 spring-boot-starter-aop 依赖,例如:

    org.springframework.bootspring-boot-starter-aop
     
     
  2. 自定义注解

    定义一个用于标记需要记录日志的方法的注解,例如:

    @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.METHOD)
     public @interface Loggable {String value() default "";
     }
     
     

    这个注解中,我们定义了一个 value 属性,用于设置日志信息的前缀。

  3. 编写切面逻辑

    创建一个切面类,实现方法执行前后的日志记录逻辑。例如:

    @Aspect
     @Component
     @Profile("dev")  // 在切面逻辑中加入条件判断,只有在开发环境才执行日志记录逻辑
     public class LoggingAspect {private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);@Before("@annotation(loggable)")public void logMethodExecution(JoinPoint joinPoint, Loggable loggable) {                        logger.info("=================start=========================================");String prefix = loggable.value();String methodName = joinPoint.getSignature().getName();String className = joinPoint.getTarget().getClass().getSimpleName();Object[] args = joinPoint.getArgs();logger.info("{}{}.{}({})", prefix, className, methodName, Arrays.toString(args));}@AfterReturning(value = "@annotation(loggable)", returning = "returnValue")public void logMethodReturnValue(JoinPoint joinPoint, Loggable loggable, Object returnValue) {String prefix = loggable.value();String methodName = joinPoint.getSignature().getName();String className = joinPoint.getTarget().getClass().getSimpleName();logger.info("{}{}.{}() returned {}", prefix, className, methodName, returnValue);}}
     
     

    这个切面类实现了方法执行前后的日志记录逻辑,分别使用了 @Before@AfterReturning 注解来标记需要拦截的方法,并使用了自定义注解 @Loggable 来标记需要记录日志的方法。在方法执行前后,我们通过获取 JoinPoint 对象中的信息来获取方法的参数和返回值,并将其记录到日志中。

  4. 在需要打印日志的方法上添加注解

    在需要打印日志的方法上添加 @Loggable 注解,并可选地设置日志信息的前缀。例如:

    @Service
     public class MyService {@Loggable("MyService:")public void doSomething(String arg1, int arg2) {// ...}}
     
     

    在这个示例代码中,我们在 doSomething 方法上添加了 @Loggable("MyService:") 注解,将日志信息的前缀设置为 "MyService:"。

  5. 运行程序并查看日志输出

    运行程序并调用 doSomething 方法,即可在控制台或日志文件中看到相应的日志输出。

  6. 结果


标签:

素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。