SSM框架16 SpringMVC简介、实例、注解实现springMVC、controller、Restful风格、重定向和转发、ModelAndView、过滤器处理乱码问题

一、SpringMVC简介

SpringMVC官方文档:https://docs.spring.io/spring-framework/docs/5.2.0.RELEASE/spring-framework-reference/
MVC是模型(model)、视图(view)、控制器(controller)的简写,是一种软件设计规范

1、用户发请求
2、servlet接收请求数据,调用对应的业务逻辑处理方法
3、业务处理完毕,返回更新后的数据给servlet
4、servlet跳转JSP,由JSP渲染页面
5、响应给前端更新后的页面

model:dao service
1、业务逻辑
2、保存数据的状态

view:jsp
显示页面

controller:servlet
1、取得表单数据
2、调用业务逻辑
3、跳转页面

SpringMVC的特点:
1、轻量级,简单易学
2、高效,基于请求响应的MVC框架
3、与Spring兼容性好,无缝结合
4、约定优于配置
5、功能强大:RESTful、数据验证、格式化、本地化、主题等
6、简洁灵活

通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。

HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找HandlerHandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。

HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。

HandlerAdapter表示处理器适配器,其按照特定的规则去执行HandlerHandler让具体的Controller执行。

Controller将具体的执行信息返回给HandlerAdapter,ModelAndViewHandlerAdapter将视图逻辑名或模型传递给DispatcherServletDispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。

视图解析器将解析的逻辑视图名传给DispatcherServletDispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。

最终视图呈现给用户。

二、简单的实例

配置一个DispatcherServlet,DispatcherServlet来找controller处理业务,controller找model获取数据,然后返回结果给DispatcherServlet,然后发请求给View跳转页面传给用户

web.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">
<!--配置DispatchServlet springmvc的核心:请求分发器,前端控制器-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--    DispatcherServlet绑定配置文件    -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
<!--        启动级别1-->
        <load-on-startup>1</load-on-startup>
    </servlet>
<!--    springMvc中 有//*
        / :只匹配所有的请求 不去匹配jsp页面
        /*:匹配所有的请求包括jsp页面
    -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

<!--    添加处理映射器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--    添加处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    <!--内部资源视图解析器 最终实现拼装成页面正确的路径-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <bean id="/hello" class="HelloController"/>



</beans>
<%--
  Created by IntelliJ IDEA.
  User: KerwinWan
  Date: 2023/2/3
  Time: 0:00
  To change this template use File | Settings | File Templates.
--%>
<%@ page isELIgnored="false" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${msg}
</body>
</html>

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import java.lang.annotation.Annotation;

public class HelloServlet implements Controller {


    @Override
    public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg","HelloServlet");
        modelAndView.setViewName("hello");
        return modelAndView;
    }
}

三、注解实现springMVC

1、web.xml版本要最新版
2、注册DispatcherServlet
3、关联SpringMVC配置文件
4、启动级为1
5、映射路径为/

<?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>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/context
                  http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!--    自动扫描包 让指定包下注解生效 IOC容器统一管理-->
    <context:component-scan base-package="controller"/>
<!--SpringMVC不处理静态资源 .css .js .html .mp3 .mp4-->
    <mvc:default-servlet-handler/>
<!--支持注解驱动
    @RequestMapping注解完成映射关系
    用annotation-driven完成了DefaultAnnotationHandlerMappingAnnotationMethodHanlderAdapter的配置
    -->
    <mvc:annotation-driven/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>



</beans>
package controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public ModelAndView hello(ModelAndView modelAndView){
        modelAndView.addObject("msg","hello");
        modelAndView.setViewName("hello");
        return modelAndView;
    }

}

四、controller控制器配置

小技巧:
改了配置文件restart
改了前端 刷新页面
改了java redeploy

通常可以由注解和实现接口两种方式实现

控制器负责解析用户的请求并将其转化为模型

五、Restful风格

restful就是一个资源定位和资源操作的风格,不是标准也不是协议,基于这个风格设计的软件更简洁、有层次,易于实现缓存等机制,最重要的是安全不容易暴漏参数

使用RESTful操作资源 : 可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!

​ http://127.0.0.1/item/1 查询,GET
​ http://127.0.0.1/item 新增,POST
​ http://127.0.0.1/item 更新,PUT
​ http://127.0.0.1/item/1 删除,DELETE

//method设置请求类型
//    @PostMapping
    @RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.PUT)
    public ModelAndView add(@PathVariable int a,@PathVariable int b, ModelAndView modelAndView){
        int result=a+b;
        modelAndView.addObject("res",result);
        modelAndView.setViewName("hello");
        return modelAndView;
    }

六、重定向和转发

    @RequestMapping("/hello")
    public ModelAndView hello(ModelAndView modelAndView){
        modelAndView.addObject("msg","hello");
        modelAndView.setViewName("hello");
        return modelAndView;
    }

    @RequestMapping("/hello")
    public String test(ModelAndView modelAndView){
        modelAndView.addObject("msg","hello");
        return "redirect:/index.jsp";
    }

七、数据处理

1、提交的域名称和处理方法的参数一致 直接拿来用
2、提交的域名称和处理方法参数不一致的时候
用@RequestParam(“username”)注释来对应上

@RequestMapping("/hello")
public String hello(@RequestParam("username") String name){
    System.out.println(name);
    return "hello";
}

3、提交的是个对象,表单域和对象的属性名一致即可
名字不一致为null

public class User {
    private int id;
    private String name;
    private int age;
    //构造
    //get/set
    //tostring()
}
@RequestMapping("/user")
public String user(User user){
    System.out.println(user);
    return "hello";
}

八、数据显示

Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解;
ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;
ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。

1、通过ModelAndView

public class ControllerTest1 implements Controller {
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //返回一个模型视图对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","ControllerTest1");
        mv.setViewName("test");
        return mv;
    }
}

2、通过ModelMap

@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap model){
    //封装要显示到视图中的数据
    //相当于req.setAttribute("name",name);
    model.addAttribute("name",name);
    System.out.println(name);
    return "hello";
}

3、通过Model

@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model){
    //封装要显示到视图中的数据
    //相当于req.setAttribute("name",name);
    model.addAttribute("msg",name);
    System.out.println(name);
    return "test";
}

九、过滤器处理乱码问题

1、在web.xml注册过滤器

<filter>
    <filter-name>encoding</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>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

2、自定义过滤器

package filter;

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

public class EncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");

        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

自定义过滤器 通用的乱码过滤器

package com.kuang.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
 * 解决get和post请求 全部乱码的过滤器
 */
public class GenericEncodingFilter implements Filter {
    @Override
    public void destroy() {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //处理response的字符编码
        HttpServletResponse myResponse=(HttpServletResponse) response;
        myResponse.setContentType("text/html;charset=UTF-8");
        // 转型为与协议相关对象
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        // 对request包装增强
        HttpServletRequest myrequest = new MyRequest(httpServletRequest);
        chain.doFilter(myrequest, response);
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}
//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {
    private HttpServletRequest request;
    //是否编码的标记
    private boolean hasEncode;
    //定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
    public MyRequest(HttpServletRequest request) {
        super(request);// super必须写
        this.request = request;
    }
    // 对需要增强方法 进行覆盖
    @Override
    public Map getParameterMap() {
        // 先获得请求方式
        String method = request.getMethod();
        if (method.equalsIgnoreCase("post")) {
            // post请求
            try {
                // 处理post乱码
                request.setCharacterEncoding("utf-8");
                return request.getParameterMap();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        } else if (method.equalsIgnoreCase("get")) {
            // get请求
            Map<String, String[]> parameterMap = request.getParameterMap();
            if (!hasEncode) { // 确保get手动编码逻辑只运行一次
                for (String parameterName : parameterMap.keySet()) {
                    String[] values = parameterMap.get(parameterName);
                    if (values != null) {
                        for (int i = 0; i < values.length; i++) {
                            try {
                                // 处理get乱码
                                values[i] = new String(values[i]
                                        .getBytes("ISO-8859-1"), "utf-8");
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                hasEncode = true;
            }
            return parameterMap;
        }
        return super.getParameterMap();
    }
    //取一个值
    @Override
    public String getParameter(String name) {
        Map<String, String[]> parameterMap = getParameterMap();
        String[] values = parameterMap.get(name);
        if (values == null) {
            return null;
        }
        return values[0]; // 取回参数的第一个值
    }
    //取所有值
    @Override
    public String[] getParameterValues(String name) {
        Map<String, String[]> parameterMap = getParameterMap();
        String[] values = parameterMap.get(name);
        return values;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值