SpringMVC

介绍

Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。【底层是servlet】
Spring的web框架围绕DispatcherServlet[调度Servlet ]设计,DispatcherServlet的作用是将请求分发到不同的处理器

特点

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

执行流程

  1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。

    我们假设请求的url为 :http://localhost:8080/SpringMVC/hello
    · 如上url拆分成三部分:
    . http://localhost:8080服务器域名
    . SpringMVC部署在服务器上的web站点. hello表示控制器
    · 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器

  2. HandlerMapping为处理器映射。DispatcherServlet调用
    HandlerMapping,HandlerMapping根据请求url查找Handler.

  3. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器如上url被查找控制器为:hello

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

  5. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler

  6. Handler让具体的Controller执行

  7. Controller将具体的执行信息返回给HandlerAdapter ,如ModelAndView

  8. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet

  9. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名

  10. 视图解析器将解析的逻辑视图名传给DispatcherServlet

  11. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图

  12. 最终视图呈现给用户。

可能遇到的问题

访问出现404,排查步骤

  1. 查看控制台输出,看下是不是缺少什么jar包
  2. 如果jar包存在,显示无法输出,就在IDEA的项目发布中,添加lib依赖!
  3. 重启Tomcat即可解决!

使用配置步骤

配置版

 1、新建一个Moudle,添加web的支持!
 2、确定导入了SpringMVC的依赖!
 3、配置web.xml,注册DispatcherServlet

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

 4、 编写SpringMVC的配置文件!名称: spring mvc-servlet.xml : [servletname]-servlet.xml说明,这里的名称要求是按照官方来的
 5、添加处理映射器
 6、添加处理器适配器
 7、添加视图解析器

   <?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.xsd">
       <!--处理器映射器-->
       <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
       <!--处理器适配器-->
       <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
       <!--视图解析器:模板引擎 Thymeleaf  Freemarker-->
       <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
           <!--前缀-->
           <property name="prefix" value="/WEB-INF/jsp/"/>
           <!--后缀-->
           <property name="suffix" value=".jsp"/>
       </bean>
   
   </beans>

 8、编写我们要操作业务Controller,要么实现Controller接口,要么增加注解;需要返回一个ModeiAndView,装数据,封视图;

public class HelloController implements Controller {
   public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
       ModelAndView mv = new ModelAndView();

       //业务代码
       String result = "HelloSpringMVC";

       mv.addObject("msg",result);
       //视图跳转
       mv.setViewName("test");

       return mv;
   }
}

 9、将自己的类交给SpringIOC容器,注册bean

   <!--BeanNameUrlHandlerMapping:bean-->
   <bean id="/hello" class="com.yf.controller.HelloController"/>

 10、写要跳转的jsp页面,显示ModelandView存放的数据,以及我们的正常页面:

注解版

 1、配置web.xml文件【具体流程和上面配置版类似】

注意点
注意web.xml版本问题,要最新版!
注册DispatcherServlet
关联SpringMVC的配置文件
启动级别为1
映射路径为/【不要用/*,会404】

 2、添加SpringMVC配置文件【springmvc-servlet.xml】

  • 让IOC的注解生效
  • 静态资源过滤:HTML . JS . CSS .图片,视频…
  • MVC的注解驱动
  • 配置视图解析器
	<?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:context="http://www.springframework.org/schema/context"
	       xmlns:mvc="http://www.springframework.org/schema/mvc"
	       xsi:schemaLocation="http://www.springframework.org/schema/beans
	       http://www.springframework.org/schema/beans/spring-beans.xsd
	       http://www.springframework.org/schema/context
	       http://www.springframework.org/schema/context/spring-context.xsd
	       http://www.springframework.org/schema/mvc
	       http://www.springframework.org/schema/mvc/spring-mvc.xsd">
	    <!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
	    <context:component-scan base-package="com.yf.controller"/>
	    <!--让Spring MVC不处理静态资源 .css  .js  .html  .mp4-->
	    <mvc:default-servlet-handler/>
	
	    <!--
	    支持mvc注解驱动
	    在spring中一般采川@RequestMapping注解来完成映射关系
	    要想使@RequestMapping注解生效
	    必须向上下文中注册DefauLtAnnotationHandLerMapping
	    和一个AnnotationMethodHandLerAdapter实倾
	    这两个实例分别在类级别和方法级别处理。
	    而annotation-driven配置帮助我们自动完成上述两个实例的注入。
	    -->
	    <mvc:annotation-driven/>
	
	    <!--视图解析器:模板引擎 Thymeleaf  Freemarker-->
	    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
	        <!--前缀-->
	        <property name="prefix" value="/WEB-INF/jsp/"/>
	        <!--后缀-->
	        <property name="suffix" value=".jsp"/>
	    </bean>
	</beans>

 3、创建Controller

@Controller
@RequestMapping("/HelloController")
public class HelloController {
   //真实访问地址:项目名/HelloController/hello
   @RequestMapping("/hello")
   public String Hello(Model model){
       //封装数据,可以在]SP页面中取出并渲染
       model.addAttribute("msg","Hello,SpringMVCAnnotation!");
       //WEB-INF/jsp/hello.jsp
       return "hello";//会被视图解析器处理,拼接
   }
}
  • @Controller是为了让Spring IOC容器初始化时自动扫描到;
  • @RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;
  • 方法中声明Model类型的参数是为了把Action中的数据带到视图中;
  • 方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp

RestFul风格

Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

使用

 1、在新建—个类RestFulController
 2、在Spring MVC中可以使用@PathVariable注解,让方法参数的值对应绑定到一个URI模板变量上。

方法级别的注解
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@Patchapping

@Controller
public class RestFulContoller {

    //原来的: http://Localhost:8080/ add?a=1&b=2
    //RestFul: http://LocaLhost:8080/add/a/b

	//两种方式
    //@RequestMapping(value = "/add/{a}/{b}",method=RequestMethod.GET)
    @GetMapping("/add/{a}/{b}")
    public String test(@PathVariable int a,@PathVariable int b, Model model){
        int res=a+b;
        model.addAttribute("msg","结果为"+res);
        return "hello";
    }
}

ModelAndVeiw

设置ModelAndView对象,根据view的名称,和视图解析器跳到指定的页面
页面:{视图解析器前缀} + viewName +{视图解析器后缀}

前端传参

当前端传递过来的参数名与字段不一致时

可以使用@RequestParam(“前端名”)的方式,或者使用RestFul风格加参数

	@RequestMapping("/t1/{username}")
    //普通方法@RequestParam("username")
    public String test1( @PathVariable("username") String name, Model model){
        //1.接收前端参数
        System.out.println("参数为:"+name);
        //2.将返回的结果传递给前端,Model
        model.addAttribute("msg",name);
        //3.视图跳转
        return "test";
    }

传递对象

1.接收前端用户传递的参数,判断参数的名字,假设名字直接在方法上,可以直接使用
2.假设传递的是一个对象User,匹配User对象中的字段名;如果名字一致则oK,否则,匹配不到显示null

	//前端接收的是一个对象:id,name,age
    @GetMapping("/t2")
    public String test2(User user){
        System.out.println(user);
        return "test";
    }

SpringMVC实现转发和重定向

有视图解析器

@Controller
public class ForwardAndRedirect {

    @RequestMapping("/forward")
    public String test(Model model){
        model.addAttribute("msg","forwardTest");
        return "hello";
    }

    @RequestMapping("/redirect")
    public String test1(Model model){
        model.addAttribute("msg","redirectTest");
        return "redirect:/index.jsp";
    }
}

无视图解析器:【不推荐】

@Controller
public class ForwardAndRedirect {

    @RequestMapping("/forward")
    public String test(Model model){
        model.addAttribute("msg","forwardTest");
        return "forward:WEB-INF/jsp/hello.jsp";
    }

    @RequestMapping("/redirect")
    public String test1(Model model){
        model.addAttribute("msg","redirectTest");
        return "redirect:/index.jsp";
    }
}

乱码问题

在POST的传值存在乱码的情况,SpringMVC有自带的过滤器为我们解决此类问题,只需在web.xml中配置一下

	<!--配置SpringMVC的乱码问题-->
	<filter>
        <filter-name>encodingFilter</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>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

但有可能在使用GET方式时出现问题,所以在网上查找到一个大佬手写的过滤器

public class GenericEncodingFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        // 处到response的字符编码
        HttpServletResponse myResponse=(HttpServletResponse) resp;myResponse.setContentType("text/html; charset=UTF-8");
        // 转型为与协议相关对象
        HttpServletRequest httpServletRequest = (HttpServletRequest) req;
        // 对request包装增强
        HttpServletRequest myrequest = new MyRequest(httpServletRequest);

        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) 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;
    }
}

拦截器

  • 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
  • 拦截器只会拦截访问的控制器方法,如果访问的是jsp/html/css/image/js是不会进行拦截的

使用

自定义一个拦截器,必须实现 Handlerlnterceptor接口。

public class Mylnterceptor implements HandlerInterceptor {
    //return true;  执行下一个拦截器
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("=====处理前=====");
        return false;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("=====处理后=====");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("=====清理=====");
    }
}

在applicationContext.xml中配置拦截器

	<!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--包含这个路径下的所有请求-->
            <mvc:mapping path="/**"/>
            <bean class="com.yf.config.Mylnterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值