SpringMVC搭建

说明:
1、项目通过maven来创建,
2、开发工具使用Intellij
3、主要内容是 spring+SpingMVC 

SpringMVC项目的一般开发流程(不包括业务层、持久层、以及数据库内容)
1、创建javaweb项目
2、导入springmvc相关依赖包
3、配置web.cml配置文件
4、配置springmvc配置文件
5、配置controller


主要内容:

pom依赖包:

<dependencies>
  <!--junit-->
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
  <!-- 导入webmvc以后,系统,自动导入所有所需依赖 -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.14.RELEASE</version>
  </dependency>
  <!-- 导入servlet依赖 -->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
  </dependency>
  <!-- 为了方便mvc获取json数据对象,可以导入jackson以下三个依赖 -->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.4</version>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.4</version>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.4</version>
  </dependency>
</dependencies>

所有jar包:

SpringMVC搭建

文件结构:

SpringMVC搭建

文件配置

applicationContext:
applicationContext.xml文件用于spring项目的全局配置,包括数据源配置、sessionFactory配置、事务配置、注解配置(注入bean依赖)等

<?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"
       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">
    <!-- 配置组件扫描器,使用注解方式开发,不用配置daoservice -->
    <!--如果工程比较简单,姐可以直接统配,如果里卖弄文件机构较为复杂,可以按需扫描文件-->
    <context:component-scan base-package="com.tsy"/>
    <!--<context:component-scan base-package="com.eduask.entity,com.eduask.dao,com.eduask.service,com.eduask.controller">

    <!- 数据源 -->
    <!--<bean id="dataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/test" />
        <property name="username" value="root" />
        <property name="password" value="" />
    </bean>-->

    <!-- 配置session工厂 -->
    <!--<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>-->

    <!-- 事务管理器 -->
    <!--<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>-->

    <!-- 配置AOP通知 -->
    <!-- <tx:advice id="txAdvice" transaction-manager="transactionManager">
         &lt;!&ndash; 配置事务属性 &ndash;&gt;
         <tx:attributes>
             &lt;!&ndash; 添加事务管理的方法 &ndash;&gt;
             <tx:method name="save*" propagation="REQUIRED"/>
             <tx:method name="delete*" propagation="REQUIRED"/>
             <tx:method name="update*" propagation="REQUIRED"/>
             <tx:method name="select*" read-only="true"/>
         </tx:attributes>
     </tx:advice>-->

    <!-- 配置AOP,为添加事务管理的操作配置AOP -->
    <!--<aop:config>
        &lt;!&ndash; 引入的Spring定义的事务通知,需要使用aop:advisor &ndash;&gt;
        &lt;!&ndash; 下面难 &ndash;&gt;
        <aop:advisor advice-ref="txAdvice"
                     pointcut="execution(* com.tsy.service.*.*(..))"
        />
    </aop:config>-->
</beans>

spring-mvc.xml
spring-mvc.xml 主要用于配置spring-mvc相关内容:比如视图解析器、controller层的扫描配置、配置静态资源的访问权限、
<?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"
       xmlns:p="http://www.springframework.org/schema/p"
       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">
    <!-- 开启mvc的注解驱动 -->
   <!-- <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean
                    class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"
                    p:supportedMediaTypes="/"/>
        </mvc:message-converters>
    </mvc:annotation-driven>-->
    <!-- annotation-driven 控制器映射器和控制器适配器 ,用来控制@Controller处理http请求的方式-->
    <mvc:annotation-driven/>
    <!--以下配置可以注释掉,系统默认就会有的-->
      <!--  <mvc:message-converters>&lt;!&ndash; register-defaults="true"表示使用默认的消息转换器 &ndash;&gt;
            &lt;!&ndash; FastJson(Spring4.2x以上版本设置) &ndash;&gt;
            &lt;!&ndash; 使用@responsebody注解并且返回值类型为String时,返回的string字符串带有双引号"{'user':'songfs'}",其原因是直接将string类型转成了json字符串,应该在json解析器之前添加字符串解析器&ndash;&gt;
            <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
            &lt;!&ndash; FastJsonHttpMessageConverter4 使@ResponseBody支持返回Map<String,Object>等类型,它会自动转换为json&ndash;&gt;
            &lt;!&ndash; 需要返回json时需要配置 produces = "application/json"。不需要再指定utf-8 &ndash;&gt;
            <bean id="fastJsonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                &lt;!&ndash; 加入支持的媒体类型 &ndash;&gt;
                <property name="supportedMediaTypes">
                    <list>
                        &lt;!&ndash; 这里顺序不能反,一定先写text/html,不然IE执行AJAX,返回JSON会出现下载文件 &ndash;&gt;
                        <value>text/html;charset=UTF-8</value>
                        <value>application/json;charset=UTF-8</value>
                        <value>application/xml;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>-->
    <!-- 自动扫描controller包下的所有类,使其默认为spring mvc的控制器 -->
    <context:component-scan base-package="com.tsy.controller"/>
    <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/pages/" p:suffix=".jsp"/>
    <!--另一种复杂写法
    <property name="prefix" value="/jsp/"></property>
         <property name="suffix" value=".jsp"></property>
            -->
    <!-- 静态资源访问  -->
    <!--<mvc:resources location="/img/" mapping="/img/**" />
    <mvc:resources location="/js/" mapping="/js/**" />
    <mvc:resources location="/css/" mapping="/css/**" />
    <mvc:resources location="WEB-INF/pages/" mapping="/page/**" />-->
    <!--<bean id="jsonConverter"
          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    </bean>
    <bean id="stringConverter"
          class="org.springframework.http.converter.StringHttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>text/plain;charset=UTF-8</value>
            </list>
        </property>
    </bean>
    <bean
            class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="stringConverter" />
                <ref bean="jsonConverter" />
            </list>
        </property>
    </bean>-->
</beans>


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">
    <display-name>spring_mvc_demo</display-name>
    <!--定制默认首页,一般可以设置为登陆或者index-->
    <!--<welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>-->

    <!--springMVC的核心分发器-->
    <servlet>
        <servlet-name>spring-mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 指定Spring的配置文件 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:spring-mvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring-mvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- spring容器配置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!-- 注意,spring加载配置文件-->
        <param-value>
            classpath*:applicationContext.xml,
        </param-value>
    </context-param>

    <!-- spring容器监听器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- charactor encoding -->
    <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>

</web-app>

说明:配置文件的注释部分,主要目的,在于,让自己了解更多的相关内容,或者配置的多种方式,拓宽自己的知识面。  正式项目里,可以去掉那些注释部分

JSP页面
index:

web-inf文件内容,拒绝客户端直接访问。  故,需要客户端通过servlet请求,由服务端调用
1、js以及ajax等方法  2、写java代码脚本进行重定向(如下),onload=“window.localtion.href='yourServlet'”


<%--
  Created by IntelliJ IDEA.
  User: TSY
  Date: 2018/4/15
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>index</title>
</head>
<body>
<h1>##########Hello World##############</h1>
<h2 style="color:blue;">开启SpringMVC之旅</h2>
<%--<a href="test/toLogin">click</a>--%>
<%--index页面自动跳转至login页面,或则实现boday标签的初始化事件--%>
<%    //request.getRequestDispatcher("index_toLoging.action").forward(request,response);
    response.sendRedirect("toLogin");
%>
</body>
</html>
register页面


<%--
  Created by IntelliJ IDEA.
  User: TSY
  Date: 2018/4/15
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>注册</title>
</head>
<body>
<form action="reg4" method="post">
    <h1>用户注册</h1>
    账号:<input type="text" name="userId"/><br/>
    密码:<input type="password" name="userPw"><br/>
    姓名:<input type="text" name="userName"/><br/>
    年龄:<input type="text" name="userAge"/><br/>
    生日:<input type="text" name="userBrithday"/><br/>
    兴趣爱好:
    <input type="checkbox" name="xqs" value="LOL"/>LOL
    <input type="checkbox" name="xqs" value="DOTA"/>DOTA
    <input type="checkbox" name="xqs" value="看电影"/>看电影
    <input type="submit" value="提交"/>
</form>
</body>
</html>
login页面
<%--
  Created by IntelliJ IDEA.
  User: TSY
  Date: 2018/4/15
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>login</title>
</head>
<body>
<a href="<%=request.getContextPath() %>toRegister">注册</a>

<form action="query5.do" method="post">
    <input type="submit" value="查询"/>
</form>
<br/>
<br/>
userId:${list[0].userPw}
<br/>
userName:${user3.userName}
userName:${user2.userName}
userName:${user1.userName}
</body>
</html>

后台源码
User实体类
SpringMVC搭建

controller层(核心内容)

package com.tsy.controller;

import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by TSY on:2018/4/15
 */
@Controller
public class TestController {
    /*
     * 如果需要页面的安全访问,web-inf下,则需要通过servlet的服务端代码。来实现跳转
     */

    /**
     * 访问内部资源(WEB-INF下)
     * 默认跳转至登陆页面
     *
     * @return "login"
     */
    @RequestMapping({"toLogin", "home"})
    public String toLogin() {
        return "login";
    }

    /**
     * 注册页面跳转
     *
     * @return "register"
     */
    @RequestMapping("toRegister")
    public String toRegister() {
        return "register";
    }

    /**
     * 通过HttpServletRequest 获取页面数据  request.getParameter 再实现页面跳转
     */
    @RequestMapping("getParameterFromJSP")
    public String demo1(HttpServletRequest request) {
        String userId = request.getParameter("userId");
        String userPw = request.getParameter("userPw");
        String userAge = request.getParameter("userAge");
        String userBrithday = request.getParameter("userBrithday");
        String xqs = request.getParameter("xqs");
        System.out.println("账号:" + userId);
        System.out.println("密码:" + userPw);
        System.out.println("年纪:" + userAge);
        System.out.println("生日:" + userBrithday);
        System.out.println("兴趣:" + xqs);
        return "login";
    }

    /**
     * 直接传参数进来。此参数名要与页面保持一致
     *
     * @param userId dd
     * @return dd
     */
    @RequestMapping("demo2")
    public String demo2(String userId, String userPw, String userAge) {
        System.out.println("姓名:" + userId);
        System.out.println("密码:" + userPw);
        System.out.println("年纪:" + userAge);
        return "login";
    }

    /**
     * 获取复选框的值:多个值/
     * RequestParam最好带上去,不然可能接收异常
     */
    @RequestMapping("reg4")
    public String reg4(@RequestParam("xqs") String[] xqs) {

        for (String xq : xqs) {
            System.out.println("兴趣:" + xq);
        }
        return "login";
    }

    /**
     * 通过对象来获取页面参数
     */
    @RequestMapping("reg5.do")
    public String reg5(User user) {

        System.out.println(user);

        return "login";
    }

    /**
     * 添加时间的属性编辑器,
     * 设置完毕以后,系统会自动识别页面传过来的信息。如果信息是时间,则会自动转换为日期格式
     */
    @InitBinder
    public void InitBinder(ServletRequestDataBinder bin) {
        bin.registerCustomEditor(Date.class, new CustomDateEditor(
                new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"), true));
    }


    /**
     * 利用ModelAndView方式,返回数据和视图
     *
     * @return dd
     */
    @RequestMapping("/query2.do")
    public ModelAndView queryUser2() {
        User u1 = new User("tom1", "123");
        User u2 = new User("tom2", "123");
        User u3 = new User("tom3", "123");

        //model
        Map<String, Object> map = new HashMap<>();
        map.put("user1", u1);
        map.put("user2", u2);
        map.put("user3", u3);
        return new ModelAndView("login", map);
    }

    /**
     * request.setAttribute的方式,返回数据和视图
     * 利用${user3.userName},可以接收参数。
     * url后面的参数,在新的页面你可以通过${param:username}接收
     *
     * @param request HttpServletRequest
     * @return 返回登陆页  其实其本身有一个刷新页面的动作
     */
    @RequestMapping("/query1.do")
    public String queryUser1(HttpServletRequest request) {

        String name = "张三";
        request.setAttribute("name", name);
        User u3 = new User("tom3", "123");
        request.setAttribute("user", u3);
        return "login";
    }

    /**
     * Map模式,返回数据和视图
     *
     * @param map aa
     * @return aa
     */
    @RequestMapping("/query3.do")
    public String queryUser3(Map<String, Object> map) {
        User u3 = new User("tom344", "12344");
        map.put("user3", u3);
        return "login";
    }

    /**
     * model模式返回数据和视图
     *
     * @param model aa
     * @return aa
     */
    @RequestMapping("/query4.do")
    public String queryUser4(Model model) {
        User u3 = new User("tom3", "123");
        model.addAttribute("user4", u3);
        return "login";
    }

    /**
     * Model模式返回List数据和视图
     *
     * @param model aa
     * @return aa
     */
    @RequestMapping("/query5.do")
    public String queryUser5(Model model) {
        User u1 = new User("tom1", "123");
        User u2 = new User("tom2", "123");
        User u3 = new User("tom3", "123");
        List<User> list = new ArrayList<>();
        list.add(u3);
        list.add(u2);
        list.add(u1);
        model.addAttribute("list", list);
        return "login";
    }

    /**
     * 比较原始的一种方式将后台数据传给页面,可以通过
     * PrintWriter out = response.getWriter();这种方式
     *
     * @param useId useId
     * @param response response
     */
    @RequestMapping("ajax1.do")
    public void ajax1(String useId, HttpServletResponse response) {
        try {
            System.out.println(useId);
            // 响应
            response.setContentType("text/html");
            response.setCharacterEncoding("utf-8");
            PrintWriter out = response.getWriter();
            if ("admin".equals(useId)) {
                out.println("对不起,您账号已经被注册,请从新输入!");
            } else {
                out.println("恭喜你,账号可以使用!");
            }
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 利用ResponseBody,可以将对象自动按照json格式,传给页面。
     * 前提是,需要有jacksonjar包的依赖(通过注解方式,就不需要在mvc的配置文件进行过多的配置)
     * ResponseBody 将内容或对象作为 HTTP 响应正文返回
     *
     * @param userId id
     * @return 返回给页面一个User对象
     */
    @ResponseBody
    @RequestMapping("/ajax2.do")
    public User ajax2(String userId) {
        System.out.println(userId);
        User u1 = new User("tom1", "123");
        if ("1001".equals(userId)) {
            u1.setUserName("悟空");
            u1.setUserPw("321");
        } else {
            u1.setUserName("八戒");
            u1.setUserPw("412");
        }
        return u1;
    }

    /**
     *
     * @return List集合
     */
    @ResponseBody
    @RequestMapping("/ajax3.do")
    public List<User> ajax3() {
        List<User> list = new ArrayList<>();
        User u1 = new User("tom1", "123");
        User u2 = new User("tom2", "123");
        User u3 = new User("tom3", "123");
        list.add(u1);
        list.add(u2);
        list.add(u3);
        return list;
    }
    /**
     *
     * @return Map集合
     */
    @ResponseBody
    @RequestMapping("/ajax4.do")
    public Map<String,User> ajax4() {
        Map<String,User> map=new HashMap<>();
        User u1 = new User("tom1", "123");
        User u2 = new User("tom2", "123");
        User u3 = new User("tom3", "123");
        map.put("testList1",u1);
        map.put("testList2",u2);
        map.put("testList3",u3);
        return map;
    }
    /**
     *
     * @return Map集合2
     */
    @ResponseBody
    @RequestMapping("/ajax5.do")
    public Map<String,List<User>> ajax5() {
        Map<String,List<User>> map=new HashMap<>();
        List<User> list = new ArrayList<>();
        User u1 = new User("tom1", "123");
        User u2 = new User("tom2", "123");
        User u3 = new User("tom3", "123");
        list.add(u1);
        list.add(u2);
        list.add(u3);
        map.put("testList1",list);
        map.put("testList2",list);
        map.put("testList3",list);
        return map;
    }
}

遗留问题:
当在controller类上使用@RequestMapping("/test"),给定统一路径时,只能有一个“/”下的动作声明,动作跳转异常(在方法上是同样情况),
http://localhost:8080/test/test/torRegister ,即会出现一个重复的路径名称,导致访问异常。 暂时还未解决。 只能不给他添加复杂的路径


答:jsp页面请求数据时,配置绝对路径,不要配置相对路径            218-05-26

注意点:
1、对于拥有日期属性的对象,   springmvc传对象进方法,需要通过initbinder设置日期格式,进行转换。
2、springMVC原理:SpringMVC搭建

SpringMVC搭建