SpringMVC-Day1 (课题有用)

第一章:三层架构和MVC 

SpringMVC是表现层的框架

1. MVC全名是Model View Controller 模型视图控制器,每个部分各司其职。

2. Model:数据模型,JavaBean的类,用来进行数据封装。

3. View:指JSP、HTML用来展示数据给用户

4. Controller:用来接收用户的请求,整个流程的控制器。用来进行数据校验等

工作流程:

浏览器向服务器发送请求——>控制器接收请求——>用javabean将数据封装起来——>与业务层交互

从业务层获得了返回的数据——>将数据封装至javabean——>程序转发至JSP,并显示结果,生成html——>响应给浏览器

第二章:SpringMVC的入门案例(重要)

1. SpringMVC的概述(查看大纲文档)

1. SpringMVC的概述

  1). 是一种基于Java实现的MVC设计模型的请求驱动类型的轻量级WEB框架

  2). Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供 了构建 Web 应用程序的全功能 MVC 模块。

  3). 使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的 SpringMVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts2(原来是表现层啊)等。

2. SpringMVC在三层架构中的位置

  1). 表现层框架

3. SpringMVC的优势:模块化

4. SpringMVC和Struts2框架的对比(面试背下来

2. SpringMVC的入门程序(重要)

1. 先创Spring_MVC空包。

创建WEB工程模块,maven的使用骨架,选择maven-archetype-webapp,新建spring_day01_01_start

到这一步会默认去网上下载插件很费时间(当时我fq才解决),我们点加号添加这一组键值对。(干啥的???

(下面这个别用了!!!!!直接点next!!!!!

 并没很快。。。而且还往c盘里下载了一大堆啥玩意?可怕。。。下载了两分钟。。(别用了!!!!!直接点next!!!!!

2.把目录补全

3.引入开发的jar包,具体的坐标如下

又开始了...每次入门为何都如此艰辛。。。

 是有什么毛病吗 dependencies好不容易都导入了 plugins又报红???

 大概是阿里云仓库没有这个2.8.2吧 碰巧web老师资料里有 复制粘贴到本地仓库,reimport解决了。

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.xxw</groupId>
  <artifactId>springmvc_day01_01_start</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>springmvc_day01_01_start Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <!--这是版本控制配置 后面dependencies们用el表达式引用它-->
    <spring.version>5.0.2.RELEASE</spring.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>

  </dependencies>

  <build>
    <finalName>springmvc_day01_01_start</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>
pom.xml

4.在web.xml里面配置servlet,叫前端控制器?(想念tomcat用注解配置多方便啊。。。)(啊啊啊其实这里其他的controller们也是的用reqMapping注解写在类上就可以对应url找到这个类,只是这个前端控制器是mvc框架的不是自己写的servlet!!!怎么我吐的槽都会被打脸)

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <!--配置前端控制器  必须是这个class(dispatcher分发器?java300集的手写服务器项目见过)-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

5.res下面新建一个springmvc.xml文件(干啥?。。spring的配置文件,这样建的自动有头信息 啊!这个就是之前的bean.xml

6.然后部署服务器,感谢弹幕提示到run里面edit里面+tomcat...把项目弄进来

以上就是环境搭建。

 开始写入门程序,发送一个请求给后台程序,后台能够接收到该请求并且执行对应的业务方法,输出一段话。并且返回一个成功的页面。

写一个controller在里面用到了@RequestMapping注解

然后配置springmvc.xml使可以扫描包用注解,但是还得在web.xml的前端控制器里面配置加载springmvc.xml的代码。。。(之前的bean.xml是谁加载classpath的来着?好像并不需要。)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启注解扫描 -->
    <context:component-scan base-package="com.xxw"/>

    <!-- 视图解析器对象 id是固定的 根据cotroller它return的名字跳转去找jsp-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- 开启SpringMVC框架注解的支持 -->
    <mvc:annotation-driven conversion-service="conversionService"/>

</beans>

入门报错:

严重 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.startup.ContextConfig.beforeStart Exception fixing docBase for context [/day01_01]
java.io.IOException: Unable to create the directory [D:LenovoQMDownload omcatapache-tomcat-8.5.31webappsday01_01]

查遍帖子都没有我这种IOException 无奈新建一个javaee模块看一看是不是版本问题之类的。最后发现是部署问题,跟着老师部署war结尾的不可以我得移除war添加用war exploded结尾的(这个是新建ee模块发现的。并不知道为什么。。。)

查了一下也没太看明白:https://blog.csdn.net/xlgen157387/article/details/56498938

其实还有一个疑问:老师jre用的路径,但ee项目显示默认的(同学说就用默认的不用跟老师一样!!!!

再运行成功出现了index.jsp里写的页面

但是点击超链接又出错了。。。。并没有跳转到success.jsp而是500了。。。狗生艰难。。。。。。。。

 网页报错:500

Type Exception Report

Message Servlet.init() for servlet [dispatcherServlet] threw exception

Description The server encountered an unexpected condition that prevented it from fulfilling the request.

Exception

javax.servlet.ServletException: Servlet.init() for servlet [dispatcherServlet] threw exception

Root Cause

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping':
Initialization of bean failed;

绝望 按exception和root cause找遍互联网也没结果。浪费狗生一天。。。。

--------------------------------------------------------------------------------------------------------------

重来一遍,让苍天知道,我不认输。。。

 放弃视频,按这个帖子来入门https://www.cnblogs.com/wmyskxz/p/8848461.html

完了我照着帖子选的springmvc4.3.18 但是自动下载的别的jdbc,tx啥的都是5.2.3版本的??希望没事。。。

不知道跳出个啥下载失败我选了个try again...try agin也没用我去。。。我的老天鹅啊为什么要这么对我

 苍天对不起,我认输。。。

----------------------------------------------------------------------------------------------------------------

吸杯奶茶 我还能站起来。。。。问了同学们她们都是跟视频成功通过了没用键值对。。。。

好,那我再再跟视频重新来一次。这次要再不行就fq下载上面的模板建工程。

心平气和,心平气和,心平气和。。。。

---------------------------------------------------------------------------------------------------------------------------------------------

 新建模块start2,用webapp模板,这次不用那个键值对,然后复制了老师的代码工程。

tomcat那个jre是默认,content还是/day01,部署那个war有exploded后缀的模块

感天动地运行成功了!!!!!!!!生活终于对我这只可怜的小猫咪露出了微笑。。(但是并不知道之前为啥是500?代码才那么几行不可能敲错啊。是那个诡异的键值对的问题??????

--------------------------------------------------------------------------------------------------------

ok...几经辗转......终于回到视频学习上.......

我们入门的过程:

1. 入门案例的执行流程

  1. 当启动Tomcat服务器的时候,因为配置了load-on-startup标签(在web.xml里面)所以会创建DispatcherServlet对象, 就会加载springmvc.xml配置文件

  2. 开启了注解扫描,那么HelloController对象就会被创建

  3. 从index.jsp发送请求,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解 找到执行的具体方法

   4. 根据执行方法的返回值,再根据配置的视图解析器,去指定的目录下查找指定名称的JSP文件

  5. Tomcat服务器渲染页面,做出响应

(我之前就是从DispacherServlet就开始不作为!!!!报错!!!不识别!!!死活不去加载springmvc.xml!!!想想就气!!!为啥啊!!!明明一模一样的代码?web.xml也配置了啊!!!难道就是那个键值对模板导致????)

 请求协议----->前端控制器DispatcherServlet------>处理器映射器HandlerMapping----->前端控制器DispatcherServlet----->处理器适配器HandlerAdapter

----->前端控制器DispatcherServlet------>视图解析器ViewResolver------->前端控制器DispatcherServlet------->1.视图渲染,将数据填充;2.发送响应协议

 (适配器具体是适配啥呢??

2.4 RequestMapping 注解

见pdf上,懒得写了

代码:

// 控制器类
@Controller
@RequestMapping(path="/user")
public class HelloController {

    /**
     * 入门案例
     * @return
     */
    //这个注解与方法建立映射关联的url 方法上的是二级目录 类上就是一级 类上写了以后,再方法就得先加类的url
    @RequestMapping(path="/hello")
    public String sayHello(){
        System.out.println("Hello StringMVC");
        return "success";//这里返回写的字符串 根据视图解析器自动跳转到对应的jsp视图
    }

    /**
     * RequestMapping注解
     * @return
     */
    @RequestMapping(value="/testRequestMapping",params = {"username=heihei"},headers = {"Accept"})
    public String testRequestMapping(){
        System.out.println("测试RequestMapping注解...");
        return "success";
    }

}
HelloController
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    <h3>入门程序</h3>

        <%--测试跳转到HelloController上的requestMapping--%>
        <%--<a href="hello">入门程序 req在方法上注解</a>--%>
        <%--<a href="/user/testRequestMapping">入门程序 req加上了类注解</a>--%>
    <a href="user/testRequestMapping?username=heihei">RequestMapping注解另一个方法上加了parm等属性</a>

</body>
</html>
index.jsp

运行结果:就是运行tomcat出来首页,点击首页的超链接跳到HelloController里匹配到对应url的方法执行,结果是控制台输出,然后方法里面还有根据适配器和视图解析器把对应的jsp页面输出。

 第三章:请求参数的绑定(重要)

1. 请求参数的绑定说明

1. 绑定机制

  1. 表单提交的数据都是k=v格式的 username=haha&password=123

  2. SpringMVC的参数绑定过程是把表单提交的请求参数作为控制器中方法的参数进行绑定的

  3. 要求:提交表单的name和参数的名称是相同的!!!

2. 支持的数据类型

  1. 基本数据类型和字符串类型

  2. 实体类型(JavaBean)

3. 集合数据类型(List、map集合等)

2. 基本数据类型和字符串类型

1. 提交表单的name和参数的名称是相同的

2. 区分大小写

3. 实体类型(JavaBean)

1. 提交表单的name和JavaBean中的属性名称需要一致

2. 如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例如: address.name

代码:

(1)首先要定义一个实体类javabean

(2)param.jsp中写一个表单!上传实体类属性们的数据,请求参数名称要和实体类对上!!

    <%--把数据封装Account类中 搞一个表单,用表单提交请求参数的数据!!!name要跟javabean的属性名相同!!!
    (xxw的Data表则是Data类!但是这非得靠表单 我那实时传感器数据如何自动填充到表单提交到服务器呢?我每走一步触发获取传感器数据提交到服务器封装成对象
    总之不是type=text手动输入上传到服务器。  这里这个action靠二级目录直接指向方法,课题就很有用!!!!--%>
    <form action="param/saveAccount" method="post">
        姓名:<input type="text" name="username" /><br/>
        密码:<input type="text" name="password" /><br/>
        金额:<input type="text" name="money" /><br/>
        <input type="submit" value="提交" />
    </form>

(3)根据action里的二级url直接指向servlet里面的方法!mvc可以把数据们封装到方法的javabean参数里面输出或保存!(课题应该是拿出计算的模值保存到list,这么想好像不用封装到bean...?  aaa我其实可以考虑mysql数据库换为sqlite啊啊啊啊离线也可以用!!!!)

/**
     * 请求参数绑定把数据封装到JavaBean的类中
     * @return
     */
    @RequestMapping("/saveAccount")
    public String saveAccount(Account account){//springmvc会自动把请求参数数据们填充到方法参数javabean对象里面
        System.out.println("执行了...");
        System.out.println(account);
        return "success";
    }

这个很有用啊啊啊啊啊!!!!!课题可以用。

运行结果:在浏览器中输入http://localhost:8080/day01/param.jsp 进入表单提交页面

输入数据

提交后,控制台方法成功输出了接收到表单数据们的实体类对象,然后跳转到了success.jsp页面

执行了...
Account{username='zhangsan', password='1007', money=1007.0}

若实体类里包含引用类型(别的实体类对象作为属性!!!)

实体类除了增加引用类型和其set,get方法外,toString方法也要记得改,不然控制台打印实体类对象时打不出引用类型 

jsp的表单这样写,也跟其他属性一样

<form action="param/saveAccount" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="text" name="password" /><br/>
金额:<input type="text" name="money" /><br/>
用户姓名:<input type="text" name="user.uname" /><br/>
用户年龄:<input type="text" name="user.age" /><br/>
<input type="submit" value="提交" />
</form>

运行结果:

 提交后控制台输出:

执行了...
Account{username='zhangsan', password='1007', money=1007.0, user=User{uname='zhangsan', age=28}}

页面跳转到success.jsp

4. 给集合属性数据封装

若实体类里包含集合!!

private List<User> list;
private Map<String,User> map;

1. JSP页面编写方式:list[0].属性

    <%--把数据封装Account类中,类中存在list和map的集合 --%>
    <form action="param/saveAccount" method="post">
        姓名:<input type="text" name="username" /><br/>
        密码:<input type="text" name="password" /><br/>
        金额:<input type="text" name="money" /><br/>
            <%--user对象泛型的数据们存到list集合的0号位上--%>
        用户姓名:<input type="text" name="list[0].uname" /><br/>
        用户年龄:<input type="text" name="list[0].age" /><br/>
        <%--String泛型的keyuser对象泛型的value数据们存到map集合的对应的key上--%>
        用户姓名:<input type="text" name="map['one'].uname" /><br/>
        用户年龄:<input type="text" name="map['one'].age" /><br/>
        <input type="submit" value="提交" />
    </form>

controller不变,依然打印对象

运行结果:

执行了...
Account{username='张艺兴', password='1007', money=1007.0, user=null, list=[User{uname='罗志祥', age=20}], map={one=User{uname='黄磊', age=21}}}

成功打印出list和map的tostring!!(忘记把引用类型注释掉了)

5. 请求参数中文乱码的解决

执行了...
Account{username='??????', post请求到服务器拿数据后,控制台输出乱码的中文名

1. 在web.xml中配置Spring提供的过滤器类

  <!--配置解决中文乱码的过滤器-->
  <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>

6. 自定义类型转换器

1. 表单提交的任何数据类型全部都是字符串类型,但是后台定义参数为Integer类型,数据也可以封装上,说明 Spring框架内部会默认进行数据类型转换

若实体类User有一个Date类型的属性,jsp表单对应cotroller里的saveUser方法

jsp:

    <%--自定义类型转换器 表单--%>
    <form action="param/saveUser" method="post">
        用户姓名:<input type="text" name="uname" /><br/>
        用户年龄:<input type="text" name="age" /><br/>
        用户生日:<input type="text" name="date" /><br/>
        <input type="submit" value="提交" />
    </form>

controller:

   /**
     * 自定义类型转换器
     * @param user
     * @return
     */
    @RequestMapping("/saveUser")
    public String saveUser(User user){
        System.out.println("执行了...");
        System.out.println(user);
        return "success";
    }

运行结果:

jsp输入

 然后报错了。。。

但是jsp输入

成功了。。。

 WHY????不服就自定义格式!

2. 如果想自定义数据类型转换,可以实现Converter的接口

  1). 自定义类型转换器

  2). 注册自定义类型转换器,在springmvc.xml配置文件中编写配置

   1).新建一个utils包StringToDateConverter类,实现Converter接口

/**
 * 把字符串转换日期
 */
public class StringToDateConverter implements Converter<String,Date>{

    /**
     * String source    传入进来字符串
     * @param source
     * @return
     */
    @Override
    public Date convert(String source) {
        // 判断
        if(source == null){
            throw new RuntimeException("请您传入数据");
        }
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        try {
            // 把按格式的字符串转换为日期
            Date date = df.parse(source);
            return date;
        } catch (Exception e) {
            throw new RuntimeException("数据类型转换出现错误");
        }
    }
}

  2).在springmvc.config配置这个类为自定义类型转换器

<!--配置自定义类型转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="cn.itcast.utils.StringToDateConverter"/>
            </set>
        </property>
    </bean>

<!-- 开启SpringMVC框架注解的支持 默认配上了映射器,适配器,解析器
 后面加上自定义的组件:自定义类型转换器-->
<mvc:annotation-driven conversion-service="conversionService"/>

.................我好像知道我之前入门为啥出错了。。。。复制这一句开启框架支持的语句,不小心把还没写的这个自定义类的配置复制进去了。。难怪前端控制器不肯去读配置文件直接罢工,因为配置文件出错了啊!!!!!!!!!。。。。。。。。。wtf..........又是被自己蠢哭的一天.............................................

运行结果:2020-10-07可以提交跳转到成功,变成2020/10/07不可以了

7. 在控制器中使用原生的ServletAPI对象

1. 只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象,然后就可以直接获得对象们了

    /**
     * 原生的API
     * @return
     */
    @RequestMapping("/testServlet")
    public String testServlet(HttpServletRequest request, HttpServletResponse response){
        //然后这里面可以像之前的servlet的doGet方法里面那样写业务逻辑
        System.out.println("执行了...");
        System.out.println(request);

        HttpSession session = request.getSession();
        System.out.println(session);

        ServletContext servletContext = session.getServletContext();
        System.out.println(servletContext);

        System.out.println(response);
        return "success";
    }
}

jsp写个超链接测试:

<a href="param/testServlet">Servlet原生的API</a>

运行结果就是控制台输出对象们的地址

----------------------------------------------------------------------------------------------------

这里是由reqMapping直至方法。web时代的servlet咋用方法来着?req get参数 然后干啥来着?复习一下

emmmmmm一复习才知道原来之前就学过用把数据们封装到对象啊,还学过两种方式封装(一种获取后调用set方法,一种用BeanUtils这个jar包,如下代码),我怎么像失忆了的nt。。。只是没这里方法的方便,mvc直接对应好了对象作为参数就行...

然后servlet里都是在doPost方法或doGet里面写业务逻辑一步一步往下写,没有像这里这样可以分成各种方法按二级url找方法

之前的web写servlet的业务是这样的:

//完成具体登录业务
@WebServlet(“/LoginServlet”)
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       //完成具体逻辑
        //1.设置编码
        request.setCharacterEncoding(“utf-8”);
/*        //2.获取请求参数
        String username = request.getParameter(“username”);
        String password = request.getParameter(“password”);
        //3.封装User对象
        User loginUser = new User();
        loginUser.setUsername(username);
        loginUser.setPassword(password);*/

        /**这次使用BeanUtils完成请求参数set到用户loginUser对象里面
         * 2.获取所有请求参数*/
        Map<String, String[]> map = request.getParameterMap();
        /**3.创建User对象*/
        User loginUser = new User();
        /**3.2使用BeanUtils封装,用populate方法完成Map到Bean里面*/
        try {
            BeanUtils.populate(loginUser,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        //4.调用UserDao的login方法
        UserDao dao = new UserDao();
        User user = dao.login(loginUser);
        //5.判断user
        if(user == null) {
            //登录跳转 转发共享
            //登录失败
            request.getRequestDispatcher(“/FailServlet”).forward(request, response);
        }else {
            //登录成功 转发时还要存储数据
            request.setAttribute(“user”,user);
            request.getRequestDispatcher(“/SuccessServlet”).forward(request, response);

        }
    }
}
LoginServlet

想起之前300集手写服务器的项目。。。简直远古时代。。。

-----------------------------------------------------------------------------------------------------

第四章:常用的注解

 新建anno.jsp 新建AnnoController

1. RequestParam注解

  1. 作用:把请求中的指定名称的参数传递给控制器中的形参赋值。(主要是解决了请求参数与controller的形参的名字不一样时无法把数据自动教给形参的问题)

  2. 属性

    1). value:请求参数中的名称

    2). required:请求参数中是否必须提供此参数,默认值是true,必须提供

  3. 代码如下

jsp中请求参数名是myname,controller中形参名为username,@requestParam这样用 写形参前面。加了以后jsp的请求参数必须是myname了就,username都不行

    @RequestMapping("/testRequestParam")
    public String testRequestParam(@RequestParam(value="myname") String username){
        System.out.println("执行了...");
        System.out.println(username);
        return "success";
    }

jsp:

<a href="anno/testRequestParam?myname=哈哈">RequestParam</a>

运行结果就控制台成功打印出了哈哈,jsp跳转到success.jsp

2. RequestBody注解

  1. 作用:用于获取请求体的内容(注意:get方法不可以所以不可以用超链接,post才有请求体,异步json会用!!!拿请求体中key value)

  2. 属性

    1). required:是否必须有请求体,默认值是true

  3. 用法代码如下

jsp表单 post提交:

    <form action="anno/testRequestBody" method="post">
        用户姓名:<input type="text" name="username" /><br/>
        用户年龄:<input type="text" name="age" /><br/>
        <input type="submit" value="提交" />
    </form>

AnnoController中写方法:

    /**
     * 获取到请求体的内容
     * @return
     */
    @RequestMapping("/testRequestBody")
    public String testRequestBody(@RequestBody String body){//注意这儿的参数不再是username或是user对象拿数据 加上注解代表想拿请求体
        System.out.println("执行了...");
        System.out.println(body);
        return "success";
    }

运行结果:

地址栏输入anno.jsp 

提交后控制台输出请求体!!!

执行了...
username=zhangsan&age=18

3. PathVariable注解

  1. 作用:绑定url中的占位符。例如:url中有/delete/{id}{id}就是占位符(则请求路径要写/delete/10)

  2. 属性

    1). value:指定url中的占位符名称

  3. Restful风格的URL(重要!!!!怎么像300集用过的那个火狐插件的名字。。。

    1). 请求路径一样,可以根据不同的请求方式去执行后台的不同方法

    2). restful风格的URL优点 :1. 结构清晰 2. 符合标准 3. 易于理解 4. 扩展方便

      可以和后面的ajax,axios完美契合 实际开发很有用

  4. 用法代码如下

controller:

/**
     * PathVariable注解
     * @return
     */
    @RequestMapping(value="/testPathVariable/{sid}")
    public String testPathVariable(@PathVariable(value="sid") String id){//这里和@RequestPrama一样诶 形参不必非为sid了??
//不过jsp根本都没写参数名直接上值10
System.out.println("执行了..."); System.out.println(id); return "success"; }

jsp:

<a href="anno/testPathVariable/10">testPathVariable</a>

运行结果:(区别是这里直接输出10而不是前面基本数据类型那里的id='10'!!这里不用管参数名key直接拿值!!课题传参好像可以直接这样啊!!

执行了...
10

4. RequestHeader注解

  1. 作用:获取指定请求头的值

  2. 属性

    1). value:请求头的名称

  3. 代码如下 不写了太简单了不重要

运行结果:(打印头信息)

执行了...
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

5. CookieValue注解

  1. 作用:用于获取指定cookie的名称的值(浏览器端存了cookie,服务器想要获取值的话用该注解)

  2. 属性

    1). value:cookie的名称

  3. 代码

<a href="anno/testCookieValue">CookieValue</a>
    /**
     * 获取Cookie的值
     * @return
     */
    @RequestMapping(value="/testCookieValue")
    public String testCookieValue(@CookieValue(value="JSESSIONID") String cookieValue){
        System.out.println("执行了...");
        System.out.println(cookieValue);
        return "success";
    }

运行结果:

执行了...
336ED963568F1A16641D249B6A53257C

6. ModelAttribute注解

  1. 作用

    1. 出现在方法上:表示当前方法会在控制器方法执行前执行。(只要给一个方法在方法上边写了这个@ModelAttribute注解,这个方法就会在任意其他方法前先执行一次。跟那个junit的@before一样。。。)

    2. 出现在参数上:获取指定的数据给参数赋值。

  2. 应用场景

    1. 当提交表单数据不是完整的实体数据时,保证没有提交的字段使用数据库原来的数据,而不是变成null。

   3. 具体的代码(得用上User实体类,请求参数名称要对上属性名称)

  jsp:写一个表单,只提交user类的uname和age,date不提交。则按mvc的自动参数绑定date那儿会是一个null。

    <form action="anno/testModelAttribute" method="post">
        用户姓名:<input type="text" name="uname" /><br/>
        用户年龄:<input type="text" name="age" /><br/>
        <input type="submit" value="提交" />
    </form>

  cotroller:

  1. 修饰的方法有返回值(User)

/**
     * ModelAttribute注解
     * @return
     */
    @RequestMapping(value="/testModelAttribute")
    public String testModelAttribute(User user){
        System.out.println("testModelAttribute执行了...");
        System.out.println(user);
        return "success";
    }
    /**
     * 该方法会先执行
     */
    @ModelAttribute
    public User showUser(String uname,int age) throws ParseException {
        System.out.println("showUser执行了...");
        // 通过用户查询数据库(模拟)
        User user = new User();
        System.out.println(uname+"+"+age);//输出了请求参数的数据们!!!神奇!这里也可以自动对应上类型!!
        user.setUname(uname);//同请求参数输入的数据 没改
        user.setAge(20);//手动改了!!但因为后面只拿表格里的所以并没有影响后面
 DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); 
user.setDate(df.parse(
"2020-05-14"));//手动改了!!因为表格里没有这一项所以后面继承了这里改的!!
  System.out.println(user); return user; }

运行结果:

表单提交

控制台输出:

showUser执行了...
joker+18
User{uname='joker', age=20, date=Thu May 14 00:00:00 CST 2020}
testModelAttribute执行了...
User{uname='joker', age=18, date=Thu May 14 00:00:00 CST 2020}

可以看出,提交的依然都保存住了没有被showUser干扰,没提交的时间继承了showUser方法的时间

  2. 修饰的方法没有返回值(void)  就在后执行写了@reqmapping的那个方法里面用@ModelAttribute在参数上获取一下先执行方法的返回值

  /**
     * 该方法会先执行
     */
    @ModelAttribute
    public void showUser(String uname, Map<String,User> map) throws ParseException {
        System.out.println("showUser执行了...");
        // 通过用户查询数据库拿出一个用户(模拟 这里直接new用户了)
        User user = new User();
        user.setUname(uname);
        user.setAge(20);//手动改了!!但因为后面只拿表格里的所以并没有影响后面
        user.setDate(new Date());//这里继承了这个手动改的因为表格没有提交这个
        map.put("abc",user);
    }
    /**
     * ModelAttribute注解
     * @return
     */
    @RequestMapping(value="/testModelAttribute")
    public String testModelAttribute(@ModelAttribute("abc") User user){
        System.out.println("testModelAttribute执行了...");
        System.out.println(user);
        return "success";
    }

运行结果:

showUser执行了...
testModelAttribute执行了...
User{uname='joker', age=18, date=Thu May 14 14:33:37 CST 2020}

7. SessionAttributes注解

   1. 作用:用于多次执行控制器方法间的参数共享(可以用调用servlet原生api得到req,用req.getSession方法获取,但那样耦合性太高)

   2. 属性

    1). value:指定存入属性的名称

  3. 代码如下

这个@SessionAttributes只能作用在类上!!

@SessionAttributes(value={"msg"})   // 把msg=美美存入到session域对中
public class AnnoController {
/**
     * SessionAttributes的注解
     * @return
     */
    @RequestMapping(value="/testSessionAttributes")
    public String testSessionAttributes(Model model){
        System.out.println("testSessionAttributes...");
        // 底层会存储到!request域!对象中,域中会显示有这么一个键值对
        model.addAttribute("msg","美美");
        return "success";
    }

success. jsp用EL显示request域

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    <h3>入门成功</h3>
<%--加上isELIgnored=false--%>
    request域对象:${requestScope}

</body>
</html>

运行结果:点击anno.jsp的超链接后跳到success.jsp

在类上加上注解以后,在success.jsp中加上打印:

<%--加上isELIgnored=false--%>
    打印request域对象:${requestScope}
    直接打印key为msg所对应的值:${ msg }
    用注解把model在req于中添加的键值对存到session域中,然后打印一下session域:${sessionScope}

运行结果:成功把键值对提到了session域里面

session域中的这个数据可以共享了。

获取和删除:

 /**
     * 获取值
     * @param modelMap
     * @return
     */
    @RequestMapping(value="/getSessionAttributes")
    public String getSessionAttributes(ModelMap modelMap){
        System.out.println("getSessionAttributes...");
        String msg = (String) modelMap.get("msg");
        System.out.println(msg);
        return "success";
    }

    /**
     * 清除
     * @param status
     * @return
     */
    @RequestMapping(value="/delSessionAttributes")
    public String delSessionAttributes(SessionStatus status){
        System.out.println("getSessionAttributes...");
        status.setComplete();
        return "success";
    }
View Code

anno.jsp里关于session方法是插入超链接跳转到success.jsp

    <a href="anno/testSessionAttributes">testSessionAttributes</a>
    <a href="anno/getSessionAttributes">getSessionAttributes</a>
    <a href="anno/delSessionAttributes">delSessionAttributes</a>

第一个是上面那个的点击超链接页面,第二个是获取session中的值在控制台输出。第三个是删除值。

原文地址:https://www.cnblogs.com/gezi1007/p/12879912.html