【SSM框架】SpringMVC笔记 — 汇总

1、什么是 SpringMVC?

SpringMVC 是基于 MVC 开发模式的框架,用来优化控制器。它是 Spring 家族的一员,它也具备 IOC 和 AOP。

  • 什么是MVC?

MVC 是一种开发模式,它是模型视图控制器的简称,所有的 web 应用都是基于 MVC 开发。

1)M:模型层,包含实体类,业务逻辑层,数据访问层

2)V:视图层,html,javaScript,vue 等都是视图层,用来显现数据

3)C:控制器,它是用来接收客户端的请求,并返回响应到客户端的组件,Servlet就是组件

2、SpringMVC 框架的优点?

1)轻量级,基于 MVC 的框架

2)易于上手,容易理解,功能强大

3)它具备 IOC 和 AOP

4)完全基于注解开发

3、Springmvc 的执行流程:

执行流程说明:

1)向服务器发送HTTP请求,请求被前端控制器 DispatcherServlet 捕获。

2)DispatcherServlet 根据

3)DispatcherServlet 根据获得的 Handler,选择一个合适的 HandlerAdapter。

4)提取 Request 中的模型数据,填充 Handler 入参,开始执行 Handler(Controller)。在填充 Handler的入参过程中,根据你的配置,Spring 将帮你做一些额外的工作:

HttpMessageConveter:将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息。

数据转换:对请求消息进行数据转换。如String转换成Integer、Double等。

数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等。

数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中。

5)Handler(Controller)执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象。

6)根据返回的ModelAndView,选择一个适合的 ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet。

7)ViewResolver 结合Model和View,来渲染视图。

8)视图负责将渲染结果返回给客户端

4、基于注解的 SpringMVC 框架开发的步骤:

1)新建项目,选择 webapp 模板

2)修改目录,添加缺失的 test 目录,java目录,resources目录(两套),并修改目录属性

3)修改 pom.xml 文件,添加 SpringMVC 的依赖,添加 Servlet 的依赖

<!--添加springmvc的依赖-->
<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-webmvc</artifactid>
    <version>5.2.5.RELEASE</version>
</dependency>
<!--添加servlet的依赖-->
<dependency>
    <groupid>javax.servlet</groupid>
    <artifactid>javax.servlet-api</artifactid>
    <version>3.1.0</version>
</dependency>

4)添加 springmvc.xml 配置文件,指定包扫描,添加视图解析器.

SpringMVC 框架为了避免请求资源路径与扩展名上的冗余,在视图解析器 InternalResouceViewResolver 中引入了请求的前辍与后辍。而 action 中只需给出要跳转页面的文件名即可,对于具体的文件路径与文件扩展名,视图解析器会自动完成拼接;

<!--添加包扫描-->
<context:component-scan base-package="com.bjpowernode.controller"></context:component-scan>
<!--添加视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--配置前缀-->
    <property name="prefix" value="/admin/"></property>
    <!--配置后缀-->
    <property name="suffix" value=".jsp"></property>
</bean>

5)删除 web.xml 文件,新建 web.xml

6)在 web.xml 文件中注册 springMVC 框架(所有的 web 请求都是基于 servlet 的)

<!--注册SpringMVC框架-->
<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>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!--
          指定拦截什么样的请求
          <a href="${pageContext.request.contextPath}/demo.action">访问服务器</a>
     -->
    <!--指定拦截以.action结尾的请求,交给核心处理器DispatcherServlet处理。-->
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

7)在 webapp 目录下新建 admin 目录,在 admin 目录下新建 main.jsp 页面,删除 index.jsp 页面,并新建

8)开发控制器(Servlet),这是一个普通的类,不用继承和实现接口。类中的每个方法就是一个具体的action控制器。

@Controller &#xA0;//&#x8868;&#x793A;&#x5F53;&#x524D;&#x7C7B;&#x4E3A;&#x5904;&#x7406;&#x5668;,&#x4EA4;&#x7ED9;Spring&#x53BB;&#x521B;&#x5EFA;&#x5BF9;&#x8C61;
public class DemoAction {
    /**
    * &#x4EE5;&#x524D;&#x7684;Servlet&#x7684;&#x89C4;&#x8303;
    * protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
    * action&#x4E2D;&#x6240;&#x6709;&#x7684;&#x529F;&#x80FD;&#x5B9E;&#x73B0;&#x90FD;&#x662F;&#x7531;&#x65B9;&#x6CD5;&#x6765;&#x5B8C;&#x6210;&#x7684;
    * action&#x65B9;&#x6CD5;&#x7684;&#x89C4;&#x8303;
    * 1)&#x8BBF;&#x95EE;&#x6743;&#x9650;&#x662F;public
    * 2)&#x65B9;&#x6CD5;&#x7684;&#x8FD4;&#x56DE;&#x503C;&#x4EFB;&#x610F;
    * 3)&#x65B9;&#x6CD5;&#x540D;&#x79F0;&#x4EFB;&#x610F;
    * 4)&#x65B9;&#x6CD5;&#x53EF;&#x4EE5;&#x6CA1;&#x6709;&#x53C2;&#x6570;,&#x5982;&#x679C;&#x6709;&#x53EF;&#x662F;&#x4EFB;&#x610F;&#x7C7B;&#x578B;
    * 5)&#x8981;&#x4F7F;&#x7528;@RequestMapping&#x6CE8;&#x89E3;&#x6765;&#x58F0;&#x660E;&#x4E00;&#x4E2A;&#x8BBF;&#x95EE;&#x7684;&#x8DEF;&#x5F84;(&#x540D;&#x79F0;)
    *
    */
    @RequestMapping("/demo")
    public String demo(){
    System.out.println("&#x670D;&#x52A1;&#x5668;&#x88AB;&#x8BBF;&#x95EE;&#x5230;&#x4E86;.......");
    return "main"; &#xA0;//&#x53EF;&#x4EE5;&#x76F4;&#x63A5;&#x8DF3;&#x5230;/admin/main.jsp&#x9875;&#x9762;&#x4E0A;
    }
}

9)添加 tomcat 进行测试功能

5、分析 web 请求:

web请求执行的流程:

index.jsp

one.jsp

  • DispatcherServlet 要在 web.xml 文件中注册才可用

6、@RequestMapping 注解详解:

  • 此注解就是来映射服务器访问的路径。@RequestMapping 的 value 属性用于定义所匹配请求的 URI。

1)此注解可加在方法上,是为此方法注册一个可以访问的名称(路径)。

@RequestMapping("/demo")
public String demo(){
System.out.println("&#x670D;&#x52A1;&#x5668;&#x88AB;&#x8BBF;&#x95EE;&#x5230;&#x4E86;.......");
return "main"; &#xA0;//&#x53EF;&#x4EE5;&#x76F4;&#x63A5;&#x8DF3;&#x5230;/admin/main.jsp&#x9875;&#x9762;&#x4E0A;
}
//<a href="${pageContext.request.contextPath}/demo.action">&#x8BBF;&#x95EE;&#x670D;&#x52A1;&#x5668;</a>

2)此注解可以加在类上,相当于是包名(虚拟路径),区分不同类中相同的 action 的名称。URI 的请求是相对于 Web 的根目录。换个角度说,要访问处理器的指定方法,必须要在方法指定 URI 之前加上处理器类前定义的模块名称。

@RequestMapping("/user")
public class DemoAction1 {..}
//<a href="${pageContext.request.contextPath}/user/demo.action">&#x8BBF;&#x95EE;&#x670D;&#x52A1;&#x5668;</a>

3)此注解可区分 get 请求和 post 请求:

  • 对于@RequestMapping,其有一个属性 method,用于对被注解方法所处理请求的提交方式进行限制,即只有满足该 method 属性指定的提交方式的请求,才会执行该被注解方法。
 @Controller
&#xA0; &#xA0; public class ReqAction {
&#xA0; &#xA0; &#xA0; &#xA0; @RequestMapping(value = "/req",method = RequestMethod.GET)
&#xA0; &#xA0; &#xA0; &#xA0; public String req(){
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; System.out.println("&#x6211;&#x662F;&#x5904;&#x7406;get&#x8BF7;&#x6C42;&#x7684;........");
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; return "main";
&#xA0; &#xA0; &#xA0; &#xA0; }
&#xA0; &#xA0; &#xA0; &#xA0; @RequestMapping(value = "/req" ,method = RequestMethod.POST)
&#xA0; &#xA0; &#xA0; &#xA0; public String req1(){
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; System.out.println("&#x6211;&#x662F;&#x5904;&#x7406;post&#x8BF7;&#x6C42;&#x7684;........");
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; return "main";
&#xA0; &#xA0; &#xA0; &#xA0; }
&#xA0; &#xA0; }

7、五种数据提交方式:

  • 前四种数据注入的方式,会自动进行类型转换。但无法自动转换日期类型。

1)单个提交数据

  • 在方法中声明一个和表单提交的参数名称相同的参数,由框架按照名称直接注入。

栗子:

/*&#xA0;
    <form action="${pageContext.request.contextPath}/one.action">
        &#x59D3;&#x540D;:<input name="myname">
        &#x5E74;&#x9F84;:<input name="age">
        <input type="submit" value="&#x63D0;&#x4EA4;">
    </form>
*/

    @RequestMapping("/one")
    public String one(String myname,int age){ &#xA0;===>&#x81EA;&#x52A8;&#x6CE8;&#x5165;,&#x5E76;&#x4E14;&#x7C7B;&#x578B;&#x8F6C;&#x6362;
        System.out.println("myname="+myname+",age="+(age+100));
        return "main";
    }

2)对象封装提交数据:

  • 声明一个自定义的实体类参数,框架调用实体类中相应的setter方法注入属性值,只要保证实体类中成员变量的名称与提交请求的name属性值一致即可。

实体类:

public class Users {
    private String name;
    private int age;
    //&#x6784;&#x9020;&#x65B9;&#x6CD5;&#xFF0C;setter&#x65B9;&#x6CD5;&#x7B49;&#x7701;&#x7565;&#x3002;&#x3002;&#x3002;
}

页面:

<form action="${pageContext.request.contextPath}/two.action" method="post">
    &#x59D3;&#x540D;:<input name="name">
    &#x5E74;&#x9F84;:<input name="age">
    <input type="submit" value="&#x63D0;&#x4EA4;">
</form>

action:

@RequestMapping("/two")
public String two(Users u){
    System.out.println(u);
    return "main";
}

3)动态占位符提交

  • 仅限于超链接或地址拦提交数据,它是一杠一值,一杠一大括号,使用注解 @PathVariable 来解析。
//<a href="${pageContext.request.contextPath}/three/&#x5F20;&#x4E09;/22.action">&#x52A8;&#x6001;&#x63D0;&#x4EA4;</a> &#xA0; &#xA0;
@RequestMapping("/three/{uname}/{uage}")
public String three(@PathVariable("uname") //&#x7528;&#x6765;&#x89E3;&#x6790;&#x8DEF;&#x5F84;&#x4E2D;&#x7684;&#x8BF7;&#x6C42;&#x53C2;&#x6570;
                    String name,
                    @PathVariable("uage")
                    int age){
    System.out.println("name="+name+",age="+(age+100));
    return "main";
}

4)映射名称不一致

  • 提交请求参数与action方法的形参的名称不一致,使用注解@RequestParam来解析
/**
* &#xA0;&#x59D3;&#x540D;:<input name="name">
* &#xA0;&#x5E74;&#x9F84;:<input name="age">
*/
@RequestMapping("/four")
public String four(@RequestParam("name") //&#x4E13;&#x95E8;&#x7528;&#x6765;&#x89E3;&#x51B3;&#x540D;&#x79F0;&#x4E0D;&#x4E00;&#x81F4;&#x7684;&#x95EE;&#x9898;
                    String uname,
                    @RequestParam("age")
                    int uage){
    System.out.println("uname="+uname+",uage="+(uage+100));
    return "main";
}

5)使用HttpServletRequest对象提取;

/**
* &#xA0;&#x59D3;&#x540D;:<input name="name">
* &#xA0;&#x5E74;&#x9F84;:<input name="age">
*/
@RequestMapping("/five")
    public String five(HttpServletRequest request){
    String name = request.getParameter("name");
    int age = Integer.parseInt(request.getParameter("age"));
    System.out.println("name="+name+",age="+(age+100));
    return "main";
} &#xA0;&#xA0;

8、中文乱码解决方案:

  • 对于前面所接收的请求参数,若含有中文,则会出现中文乱码问题。Spring 对于请求参数中的中文乱码问题,给出了专门的字符集过滤器:
  • spring-web-5.2.5.RELEASE.jar 的 org.springframework.web.filter 包下的 CharacterEncodingFilter 类。

解决方案:

  • 在 web.xml 中注册字符集过滤器,即可解决 Spring 的请求参数的中文乱码问题。不过,最好将该过滤器注册在其它过滤器之前。因为过滤器的执行是按照其注册顺序进行的。
<filter>
    <filter-name>encode</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!--
            配置参数
            private String encoding;
            private boolean forceRequestEncoding;
            private boolean forceResponseEncoding;
        -->
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceRequestEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>forceResponseEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encode</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

9、action方法的返回值:

1)String:

处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析可以将其转换为物理视图地址;

可以自动拼接前缀和后缀,可以指定返回的路径;

当然,也可以直接返回资源的物理视图名。不过,此时就不需要再在视图解析器中再配置前辍与后辍了。

2)Object:

返回 json 格式的对象,自动将对象或集合转为 json,使用的 jackson 工具进行转换,必须要添加 jackson 依赖,一般用于 ajax 请求;

处理器方法也可以返回 Object 对象,这个 Object 可以是 Integer,自定义对象,Map,List 等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。返回对象,需要使用@ResponseBody 注解,将转换后的 JSON 数据放入到响应体中。Ajax请求多用于Object返回值类型。

3)void:

无返回值,一般用于ajax请求;

若处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void。

4)基本数据类型,用于 ajax 请求。

5)ModelAndView:返回数据和视图对象,现在用的很少。

10、完成 ajax 请求访问服务器,返回学生集合:

1)添加jackson依赖

<dependency>
    <groupid>com.fasterxml.jackson.core</groupid>
    <artifactid>jackson-databind</artifactid>
    <version>2.9.8</version>
</dependency>

2)在 webapp 目录下新建 js目录,添加 jQuery 函数库

3)在 index.jsp 页面上导入函数库:

4)在 action 上添加注解@ResponseBody,用来处理ajax请求

@Controller
public class AjaxAction {
    //&#x5904;&#x7406;ajax&#x8BF7;&#x6C42;,&#x4E00;&#x5B9A;&#x8981;&#x52A0;@ResponseBody
    @ResponseBody
    @RequestMapping("/ajax")
    public List<student> ajax(){
        Student stu1 = new Student("&#x5F20;&#x4E09;",22);
        Student stu2 = new Student("&#x674E;&#x56DB;",24);
        Student stu3 = new Student("&#x738B;&#x4E94;",23);
        List<student> list = new ArrayList<>();
        list.add(stu1);
        list.add(stu2);
        list.add(stu3);
        //&#x8C03;&#x7528;json&#x8F6C;&#x6362;&#x5DE5;&#x5177;ObjectMapper&#x8FDB;&#x884C;&#x8F6C;&#x6362;
        return list; &#xA0;//===>springmvc&#x8D1F;&#x8D23;&#x8F6C;&#x6362;&#x6210;json
        }
    }</student></student>

5)在 springmvc.xml 文件中添加注解驱动

<mvc:annotation-driven></mvc:annotation-driven>

11、SpringMVC 的四种跳转方式:

  • 本质就是两种跳转:请求转发和重定向,衍生出四种是请求转发页面,转发action,重定向页面,重定向action;
  • 默认的跳转是请求转发,直接跳转到 jsp 页面展示;

可以使用框架提供的关键字 redirect: ,进行一个重定向操作,包括重定向页面和重定向action;

可以使用框架提供的关键字forward:,进行服务器内部转发操作,包括转发页面和转发action;

  • 当使用 redirect: 和 forward: 关键字时,视图解析器中前缀后缀的拼接就无效了。

栗子:

@RequestMapping("/one")
public String one(){
    System.out.println("&#x8FD9;&#x662F;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;&#x9875;&#x9762;&#x8DF3;&#x8F6C;.........");
    return "main"; &#xA0;//&#x9ED8;&#x8BA4;&#x662F;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;,&#x4F7F;&#x7528;&#x89C6;&#x56FE;&#x89E3;&#x6790;&#x5668;&#x62FC;&#x63A5;&#x524D;&#x7F00;&#x540E;&#x7F00;&#x8FDB;&#x884C;&#x9875;&#x9762;&#x8DF3;&#x8F6C;
}

@RequestMapping("/two")
public String two(){
    System.out.println("&#x8FD9;&#x662F;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;action&#x8DF3;&#x8F6C;.........");
    // &#xA0;/admin/ &#xA0;/other.action &#xA0;.jsp
    //forward: &#x8FD9;&#x7EC4;&#x5B57;&#x7B26;&#x4E32;&#x53EF;&#x4EE5;&#x5C4F;&#x853D;&#x524D;&#x7F00;&#x548C;&#x540E;&#x7F00;&#x7684;&#x62FC;&#x63A5;.&#x5B9E;&#x73B0;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;&#x8DF3;&#x8F6C;
    return "forward:/other.action"; &#xA0;//&#x9ED8;&#x8BA4;&#x662F;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;,&#x4F7F;&#x7528;&#x89C6;&#x56FE;&#x89E3;&#x6790;&#x5668;&#x62FC;&#x63A5;&#x524D;&#x7F00;&#x540E;&#x7F00;&#x8FDB;&#x884C;&#x9875;&#x9762;&#x8DF3;&#x8F6C;
}

@RequestMapping("/three")
public String three(){
    System.out.println("&#x8FD9;&#x662F;&#x91CD;&#x5B9A;&#x5411;&#x9875;&#x9762;.......");
    //redirect: &#xA0;&#x8FD9;&#x7EC4;&#x5B57;&#x7B26;&#x4E32;&#x53EF;&#x4EE5;&#x5C4F;&#x853D;&#x524D;&#x7F00;&#x548C;&#x540E;&#x7F00;&#x7684;&#x62FC;&#x63A5;.&#x5B9E;&#x73B0;&#x91CD;&#x5B9A;&#x5411;&#x8DF3;&#x8F6C;
    return "redirect:/admin/main.jsp";
}

@RequestMapping("/four")
public String four(){
    System.out.println("&#x8FD9;&#x662F;&#x91CD;&#x5B9A;&#x5411;action.......");
    //redirect: &#xA0;&#x8FD9;&#x7EC4;&#x5B57;&#x7B26;&#x4E32;&#x53EF;&#x4EE5;&#x5C4F;&#x853D;&#x524D;&#x7F00;&#x548C;&#x540E;&#x7F00;&#x7684;&#x62FC;&#x63A5;.&#x5B9E;&#x73B0;&#x91CD;&#x5B9A;&#x5411;&#x8DF3;&#x8F6C;
    return "redirect:/other.action";
}

@RequestMapping("/five")
public String five(){
    System.out.println("&#x8FD9;&#x662F;&#x968F;&#x4FBF;&#x8DF3;.......");

    return "forward:/fore/login.jsp";
}

12、SpringMVC 默认的参数类型:

不需要去创建,直接拿来使用即可。

1)HttpServletRequest

2)HttpServletResponse

3)HttpSession

4)Model

5)Map

6)ModelMap

栗子:

//&#x505A;&#x4E00;&#x4E2A;&#x6570;&#x636E;,&#x4F20;&#x5230;main.jsp&#x9875;&#x9762;&#x4E0A;
Users u = new Users("&#x5F20;&#x4E09;",22);

//&#x4F20;&#x9012;&#x6570;&#x636E;
request.setAttribute("requestUsers",u);
session.setAttribute("sessionUsers",u);
model.addAttribute("modelUsers",u);
map.put("mapUsers",u);
modelMap.addAttribute("modelMapUsers",u);

注意:Map,Model,ModelMap 和 request 一样,都使用请求作用域进行数据传递,所以服务器端的跳转必须是请求转发,页面才可以得到值。

13.日期处理:

1)日期的提交处理

A、单个日期处理

  • 要使用注解@DateTimeFormat,此注解必须搭配 springmvc.xml 文件中的

在方法的参数上使用@DateTimeFormat注解;

在类的成员setXXX()方法上使用@DateTimeFormat注解

  • 但这种解决方案要在每个使用日期类型的地方都去添加使用@DateTimeFormat注解,比较麻烦,我们可以使用@InitBinder注解来进行类中统一日期类型的处理。

B.类中全局日期处理

注册一个注解,用来解析本类中所有的日期类型,自动转换

@InitBinder&#xFF1B;
public void initBinder(WebDataBinder dataBinder){
    dataBinder.registerCustomEditor(Date.class,new CustomDateEditor(sf,true));
}

2)日期的显示处理:

  • 在页面上显示好看的日期,必须使用 JSTL

步骤:

A)添加依赖 jstl

<dependency>
    <groupid>jstl</groupid>
    <artifactid>jstl</artifactid>
    <version>1.2</version>
</dependency>

B)在页面上导入标签库 :

  • 如果是单个日期对象,直接转为好看的格式化的字符串进行显示

如果是 list 中的实体类对象的成员变量是日期类型,则必须使用 jstl 进行显示。

<%--导入jstl核心标签库--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--导入jstl格式化标签库--%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %></%@taglib></%--导入jstl格式化标签库--%></%@taglib></%--导入jstl核心标签库--%>

C)使用标签显示数据:

<table width="800px" border="1">
    <tr>
        <th>&#x59D3;&#x540D;</th>
        <th>&#x751F;&#x65E5;</th>
    </tr>
    <c:foreach items="${list}" var="stu">
        <tr>
            <td>${stu.name}</td>
            <td>${stu.birthday}------ <fmt:formatdate value="${stu.birthday}" pattern="yyyy-MM-dd"></fmt:formatdate></td>
        </tr>
    </c:foreach>
</table>

14、SpringMVC 的拦截器:

  • 针对请求和响应进行的额外的处理,在请求和响应的过程中添加预处理,后处理和最终处理

&#x62E6;&#x622A;&#x5668;&#x6267;&#x884C;&#x7684;&#x65F6;&#x673A;&#xFF1A;

1)preHandle():在请求被处理之前进行操作(预处理)

2)postHandle():在请求被处理之后,但结果还没有渲染前进行操作,可以改变响应结果(后处理)

3)afterCompletion:所有的请求响应结束后执行善后工作,清理对象,关闭资源(最终处理)

&#x62E6;&#x622A;&#x5668;&#x5B9E;&#x73B0;&#x7684;&#x4E24;&#x79CD;&#x65B9;&#x5F0F;&#xFF1A;

1)继承 HandlerInterceptorAdapter 的父类

2)实现 HandlerInterceptor 接口

&#x62E6;&#x622A;&#x5668;&#x5B9E;&#x73B0;&#x7684;&#x6B65;&#x9AA4;&#xFF1A;

1)创建登录方法,在 session 中存储用户信息,用于进行权限验证

@RequestMapping("/login")
public String login(String name, String pwd, HttpServletRequest request){
    if("zar".equalsIgnoreCase(name) && "123".equalsIgnoreCase(pwd)){
        //&#x5728;session&#x4E2D;&#x5B58;&#x50A8;&#x7528;&#x6237;&#x4FE1;&#x606F;,&#x7528;&#x4E8E;&#x8FDB;&#x884C;&#x6743;&#x9650;&#x9A8C;&#x8BC1;
        request.getSession().setAttribute("users",name);
        return "main";
    }else{
        request.setAttribute("msg","&#x7528;&#x6237;&#x540D;&#x6216;&#x5BC6;&#x7801;&#x4E0D;&#x6B63;&#x786E;!");
        return "login";
    }
}

2)开发拦截器的功能,实现 HandlerInterceptor 接口,重写 preHandle() 方法:

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //&#x662F;&#x5426;&#x767B;&#x5F55;&#x8FC7;&#x7684;&#x5224;&#x65AD;
        if(request.getSession().getAttribute("users") == null){
            //&#x6B64;&#x65F6;&#x5C31;&#x662F;&#x6CA1;&#x6709;&#x767B;&#x5F55;,&#x6253;&#x56DE;&#x5230;&#x767B;&#x5F55;&#x9875;&#x9762;,&#x5E76;&#x7ED9;&#x51FA;&#x63D0;&#x793A;
            request.setAttribute("msg","&#x60A8;&#x8FD8;&#x6CA1;&#x6709;&#x767B;&#x5F55;,&#x8BF7;&#x5148;&#x53BB;&#x767B;&#x5F55;!");
            request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
            return false;
        }
        return true;//&#x653E;&#x884C;&#x8BF7;&#x6C42;
    }
}

3)在 springmvc.xml 文件中注册拦截器:

<mvc:interceptors>
    <mvc:interceptor>
        <!--映射要拦截的请求-->
        <mvc:mapping path="/**">
        <!--设置放行的请求-->
        <mvc:exclude-mapping path="/showLogin"></mvc:exclude-mapping>
        <mvc:exclude-mapping path="/login"></mvc:exclude-mapping>
        <!--配置具体的拦截器实现功能的类-->
        <bean class="com.bjpowernode.interceptor.LoginInterceptor"></bean>
    </mvc:mapping></mvc:interceptor>
</mvc:interceptors>

&#xA0;&#x8D44;&#x6E90;&#x5728;WEB-INF&#x76EE;&#x5F55;&#x4E0B;&#xFF1A;

很多企业会将动态资源放在WEB-INF目录下,这样可以保证资源的安全性,因为在WEB-INF目录下的动态资源不可以直接访问,必须要通过请求转发的方式进行访问,这样避免了通过地址栏直接对资源的访问,重定向也无法访问动态资源。

栗子:

@Controller
public class WebInfAction {
    @RequestMapping("/showMain")
    public String showMain(){//&#x901A;&#x8FC7;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;&#x7684;&#x65B9;&#x5F0F;&#x8BBF;&#x95EE;webapp&#x76EE;&#x5F55;&#x4E0B;&#x7684;WEB-INF&#x76EE;&#x5F55;&#x4E0B;&#x7684;main.jsp
        System.out.println("&#x8BBF;&#x95EE;main.jsp");
        return "main";
    }
    @RequestMapping("/showLogin")
    public String showLogin(){////&#x901A;&#x8FC7;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;&#x7684;&#x65B9;&#x5F0F;&#x8BBF;&#x95EE;webapp&#x76EE;&#x5F55;&#x4E0B;&#x7684;WEB-INF&#x76EE;&#x5F55;&#x4E0B;&#x7684;login.jsp
        System.out.println("&#x8BBF;&#x95EE;login.jsp");
        return "login";
    }
}

Original: https://www.cnblogs.com/Burning-youth/p/16342656.html
Author: 猿头猿脑的王狗蛋
Title: 【SSM框架】SpringMVC笔记 — 汇总

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/586390/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 解决图片上传后,不刷新图片

    后端上传图片后是覆盖原来图片,上传图片后返回的图片访问路径,是和原来是一样的;浏览器有缓存,看到访问的新路径是和原来一样的,所以浏览器访问的是缓存中的图片;可以给返回的访问路径拼接…

    Java 2023年6月8日
    072
  • 4 信息的表示和处理_信息存储

    开头:本章研究在计算机上如何表示数字和其它形式数据的基本属性,以及计算机对这些数据执行操作的属性。 注意:这部分谈到的内存,并不是指硬件中的内存条,而是在《计算机系统漫游》章节中的…

    Java 2023年6月7日
    068
  • Linux基操

    1 解压命令:tar -zxcf [压缩包名] 2 &…

    Java 2023年6月8日
    070
  • JAVA字符串格式化-String.format()的使用

    常规类型的格式化 String类的format()方法用于创建格式化的字符串以及连接多个字符串对象。熟悉C语言的同学应该记得C语言的sprintf()方法,两者有类似之处。form…

    Java 2023年5月29日
    072
  • Day8

    package method;public class Demo4 { public static void main(String[] args) { Demo4 d= new …

    Java 2023年6月5日
    054
  • mock测试出现Circular view path [trade_records]: would dispatch back to the current handler URL

    这是因为你的Controller中返回的视图名称与你当前的requestMapping名称一样,这并没有很好的解决方案,除非你改掉其中一个名字。 因为springframework…

    Java 2023年6月7日
    0123
  • Spring Cache缓存框架

    Spring Cache是Spring体系下标准化缓存框架。Spring Cache有如下优势: *缓存品种多 *平滑迁移 Spring内部支持的缓存,可实现无缝平滑迁移,无需修改…

    Java 2023年6月6日
    053
  • IOS html页面输入框焦点获取和释放时,页面滚动技巧

    var htmlScrollHeight = $(document).scrollTop();//记录页面初始滚动条到顶部的高度 $(‘input’).bl…

    Java 2023年6月5日
    060
  • input框设置禁用状态

    input设置为不可编辑的状态(三种方法,可自行选择) 1. disabled 属性规定应该禁用 input 元素,被禁用的 input 元素,不可编辑,不可复制,不可选择,不能接…

    Java 2023年6月5日
    066
  • CS144lab笔记

    下面看代码: lab0 webget.cc 点击查看代码 webget.cc byte_stream.hh 点击查看代码 // ccm #ifndef SPONGE_LIBSPON…

    Java 2023年6月5日
    068
  • @Configuration(proxyBeanMethods = true)

    @Configuration(proxyBeanMethods = true) @Configuration写在类上,表示该类是个配置类。 springboot2中新加入的参数 p…

    Java 2023年6月8日
    067
  • 真·Android Zxing 扫码中文乱码解决

    Zxing3.2.1 之前遇到过Android Zxing扫码乱码的问题,网上搜了下解决了下。 今天又遇到了问题。 依然会乱码。 研究总结如下: Zxing 可以在Hints中添加…

    Java 2023年6月15日
    066
  • 头秃了,使用@AutoConfigureBefore指定配置类顺序竟没生效?

    日常工作中对于 Spring Boot 提供的一些启动器可能已经足够使用了,但是不可避免的需要自定义启动器,比如整合一个陌生的组件,也想要达到开箱即用的效果。 这篇文章将会介绍如何…

    Java 2023年6月14日
    068
  • Spring Boot + Spring Cloud 实现权限管理系统 后端篇(十七):登录验证码实现(Captcha)

    登录验证码 登录验证是一般系统都会有的功能,验证的方式也多种多样,比如输入式验证码,拖动式验证条,拖动式验证拼图等等。 我们这里先实现常规的输入验证码的方式,右边显示验证码图片,点…

    Java 2023年5月30日
    081
  • JMeter While循环控制器应用之遍历获取文件参数

    作者:授客微信/QQ:1033553122全国软件测试QQ交流群:7156436Git地址:https://gitee.com/ishouke友情提示:限于时间仓促,文中可能存在错…

    Java 2023年6月16日
    057
  • Spring-AOP学习笔记

    Spring 是轻量级的开源的 JavaEE 框架。 Spring有两个核心部分IOC 和 Aop IOC(Inversion of Control):控制反转,把创建对象过程交给…

    Java 2023年6月8日
    064
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球