Java框架Spring(三)

一、ssm框架

早期的ssm == spring +struts2 + mybaits

早期的spring框架没有进行web层封装,需要集成struts2使用

现在的ssm == spring+springWeb+myBatis

实际上springWeb只是spring框架中的一个模块,只是大家叫习惯了,所有仍然称为ssm

二、springWeb

1、springWeb介绍

SpringWeb 是spring框架中的一个模块基于Servlet API构建的web框架.

springWeb 是Spring 为web层开发提供的一整套完备的解决方案。

在web层框架历经Strust1,WebWork,Strust2 等诸多产品的历代更选之后, 目前业界普遍选择了springWeb作为JavaEE项目web层开发的首选方案

2、springWeb的特点

SpringWEB是spring 家族原生产品,与IOC容器等基础设施无缝对接.

基于原生的Servlet,提供了一个前端控制器 DispatcherServlet ,开发者 无须额外开发控制器对象.

可以自动绑定用户输入,并正确地转换数据类型.

代码清新简洁,大幅度提升开发效率.

内部组件化程度高,可插拔式组件即插即用.

性能卓著,尤其适合现代大型、超大型互联网项目要求

3、springWeb运行流程

(1)springWeb组件

1)、前端控制器:

DispatcherServlet(不需要程序员开发),由框架提供,在 web.xml 中配置。

作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理 用户的请求.

2)、处理器映射器:

HandlerMapping(不需要程序员开发),由框架提供。

作用:根据请求的url查找Handler(处理器/Controller)

3)、处理器适配器:

HandlerAdapter(不需要程序员开发),由框架提供。

作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler。

4)、处理器:Handler(也称之为Controller,需要工程师开发)。

注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可 以去正确执行Handler。

作用:接受用户请求信息,调用业务方法处理请求,也称之为后端控制器。

(2)流程

流程图中,只有拦截器和自定义处理器handler需要程序员自己编写

4、搭建SpringWeb

(1)导入jar包

复制代码
<!--springWeb-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
    </dependencies>

(2)配置DispatcherServlet

在web.xml文件中配置DispatcherServlet 配置spring核心请求分发器

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>application</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring.xml</param-value>
        </init-param>
        <load-on-startup>0</load-on-startup>
    </servlet>
    <!--请求映射-->
    <servlet-mapping>
        <servlet-name>application</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

(3)开启SpringWEB注解

在spring配置文件中配置

复制代码
<!--开启web注解-->
<mvc:annotation-driven></mvc:annotation-driven>

(4) 处理器类搭建

java 复制代码
package com.wbc.ssm.web;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController//通过spring IOC管理
@RequestMapping(path = "loginCtl")//类的地址
public class LoginController {

    @RequestMapping(path = "login")//方法的地址
    public String login(){
        System.out.println("登录");
        return "success";
    }
}

解释:

1、@RestController

用于标记在一个类上,使用它标记的类就是一个SpringWEB 控制器类(类似于@service...使得spring可以反转控制)

2、@RequestMapping(path = "")

可以用于配置类的地址和方法的地址(在类上面定义地址是不能重复的),通过地址可以让前端访问服务器

(5)获取请求

我们可以通过 apiPost模拟前端发送请求

Apipost-API 文档、设计、调试、自动化测试一体化协作平台

这里以apipost8为例

1)、定义请求方法的标签
复制代码
@RequestMapping(path = "login1",method = RequestMethod.GET)//方法的地址
@RequestMapping(path = "login1",method = RequestMethod.POST)//方法的地址
@GetMapping(path = "login1")
@PostMapping(path = "login1")
2)、几种请求方法
通过原始的HttpServletRequest request, HttpServletResponse response接收
复制代码
@RequestMapping(path = "login1",method = RequestMethod.POST)
public String login1(HttpServletRequest request, HttpServletResponse response){
    System.out.println(request.getParameter("account"));
    System.out.println(request.getParameter("password"));
    return "success";
}
自动注入对应的参数

参数名和请求数据名称必须一致,不一致需要通过在参数前添加注解@RequestParam("别名")

请求头中传入参数需要使用@RequestHeader("名称")接到参数

如果请求的数据类型和参数的类型不匹配,则会返回状态码400

复制代码
//2、自动注入到对应参数
// 参数名和请求数据名称必须一致,不一致需要通过在参数前添加注解@RequestParam("别名") 如果在请求头中需要使用@RequestHeader("名称")接到参数
//如果请求的数据类型和参数的类型不匹配,则会返回状态码400
@RequestMapping(path = "login2",method = RequestMethod.POST)
public String login2(@RequestParam("account1") String account,@RequestHeader("user-password") String password){
    System.out.println(account);
    System.out.println(password);
    return "success";
}
自动注入到对象
复制代码
//通过对象接收
@PostMapping(path = "login3")
public String login3(Admin admin,@RequestHeader("adminToken") String adminToken){
    System.out.println(adminToken);
    System.out.println(admin.getAccount());
    System.out.println(admin.getPassword());
    return "success";
}
接收json

接收json需要在对象前添加@RequestBody注解

复制代码
//接收json
@PostMapping(path = "login4")
public String login4(@RequestBody Admin admin,@RequestHeader("adminToken") String adminToken){
    System.out.println(adminToken);
    System.out.println(admin.getAccount());
    System.out.println(admin.getPassword());
    return "success";
}

接收日期

需要在属性上方添加注释@DateTimeFormat(pattern="yyyy-MM-dd")

复制代码
@DateTimeFormat(pattern = "yyyy-MM-dd")//接收前端提交数据的日期格式
@JsonFormat(pattern = "yyyy-MM-dd")//后端向前端转json时的日期格式
private Date birthday;

(6)通过Result类相应

我这里安装了lombok组件,自动生成set get toString equals hashCode等方法,并且通过@AllArgsConstructor生成满参构造方法、@NoArgsConstructor//构造无参构造方法。如果没有安装lombok组件的同学需要自行生成相关方法

java 复制代码
package com.wbc.ssm.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

@Component
/*
    lombok 自动生成set get toString equals hashCode
*/
@Data
@AllArgsConstructor//生成满参构造方法
@NoArgsConstructor//构造无参构造方法
public class Result {
    private int code;
    private String message;
    private Object data;

}

通过Result直接返回响应

java 复制代码
@PostMapping(path = "login5")
    public Result login5(Admin admin,@RequestHeader("adminToken") String adminToken){
        System.out.println(adminToken);
        List<Admin> admins = loginService.login();
        Result result = new Result(200,"success",admins);
        return result;
    }

(7)搭建拦截器

Spring WEB中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter), 它主要用于拦截用户请求并作相应的处理。

Spring 中的拦截器与过滤器有着本质的区别,过滤器是servlet规范中定义 并实现的,在进入到servlet之前截获请求 .而拦截器是spring中定义 的一种拦截机制, 是对进入到处理器的请求进行拦截

1)拦截器实现

SpringWEB 定义了拦截器接口HandlerInterceptor 我们通过实现此接口并重写boolean preHandle方法进行拦截器布置。

我们这里通过创建模拟验证token的拦截器为例

创建一个类来实现HandlerInterceptor接口并重写preHandle方法

java 复制代码
package com.wbc.ssm.Interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wbc.ssm.model.Result;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class AdminTokenInterceptor implements HandlerInterceptor {

/*
    拦截器处理方法
    当请求达到处理器前,进入到拦截器进行处理
    返回true--离开拦截器向后执行到达处理器
    返回flase--不再向后执行
*/
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String adminToken = request.getHeader("adminToken");
        if (adminToken.equals("123456")) {
            return true;
        }
        else {
            System.out.println("adminToken:"+adminToken);
            Result result = new Result(401,"adminToken验证失败",null);
            response.getWriter().write(new ObjectMapper().writeValueAsString(result));
        }
        return false;
    }
}

在spring.xml全局配置文件中进行配置

复制代码
<!--配置token拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--所有地址都进入此拦截器-->
        <mvc:mapping path="/**"/>
        <!--除了/loginCtl/login5 方法-->
        <mvc:exclude-mapping path="/loginCtl/login5"/>
        <!--配置其id和类的位置-->
        <bean id="admintoken" class="com.wbc.ssm.Interceptor.AdminTokenInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

测试两个方法能否过拦截器

登录可过,测试过不去

说明拦截器搭建成功

2)编码拦截器

在不适用框架时,我们需要自己创建编码过滤器

java 复制代码
package com.wbc.dorm.filter;


import javax.servlet.*;
import java.io.IOException;

public class EncodingFilter implements Filter {

    String reqencod="";
    String respencod="";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化过滤器");
        reqencod=filterConfig.getInitParameter("reqencod");
        respencod=filterConfig.getInitParameter("respencod");
    }

    @Override
    public void destroy() {
        System.out.println("过滤器销毁时执行");
    }

    //执行过滤操作的方法
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("编码过滤器");
        //设置请求编码集
        servletRequest.setCharacterEncoding(reqencod);
        //设置响应编码集
        servletResponse.setContentType(respencod);
        //让请求离开过滤器,继续向下执行,下一个可能是过滤器,也可能是目标访问的servlet
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

并在web.xml中配置

XML 复制代码
<filter>
        <filter-name>encoding</filter-name>
        <filter-class>com.wbc.dorm.filter.EncodingFilter</filter-class>
        <init-param>
            <param-name>reqencod</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <init-param>
            <param-name>respencod</param-name>
            <param-value>text/html;charset=utf-8</param-value>
        </init-param>
    </filter>

在使用spring框架时,框架给我们写好了相应的拦截器,只需要在web.xml中配置即可

XML 复制代码
 <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
相关推荐
@东辰几秒前
【golang-技巧】-自定义k8s-operator-by kubebuilder
开发语言·golang·kubernetes
Hello-Brand几秒前
Java核心知识体系10-线程管理
java·高并发·多线程·并发·多线程模型·线程管理
乐悠小码6 分钟前
数据结构------队列(Java语言描述)
java·开发语言·数据结构·链表·队列
史努比.8 分钟前
Pod控制器
java·开发语言
2的n次方_11 分钟前
二维费用背包问题
java·算法·动态规划
皮皮林55111 分钟前
警惕!List.of() vs Arrays.asList():这些隐藏差异可能让你的代码崩溃!
java
莳光.11 分钟前
122、java的LambdaQueryWapper的条件拼接实现数据sql中and (column1 =1 or column1 is null)
java·mybatis
程序猿麦小七16 分钟前
基于springboot的景区网页设计与实现
java·spring boot·后端·旅游·景区
敲敲敲-敲代码17 分钟前
游戏设计:推箱子【easyx图形界面/c语言】
c语言·开发语言·游戏
weisian15123 分钟前
认证鉴权框架SpringSecurity-2--重点组件和过滤器链篇
java·安全