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包:
文件结构:
文件配置
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"> <!-- 配置组件扫描器,使用注解方式开发,不用配置dao和service --> <!--如果工程比较简单,姐可以直接统配,如果里卖弄文件机构较为复杂,可以按需扫描文件--> <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"> <!– 配置事务属性 –> <tx:attributes> <!– 添加事务管理的方法 –> <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> <!– 引入的Spring定义的事务通知,需要使用aop:advisor –> <!– 下面难 –> <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><!– register-defaults="true"表示使用默认的消息转换器 –> <!– FastJson(Spring4.2x以上版本设置) –> <!– 使用@responsebody注解并且返回值类型为String时,返回的string字符串带有双引号"{'user':'songfs'}",其原因是直接将string类型转成了json字符串,应该在json解析器之前添加字符串解析器–> <bean class="org.springframework.http.converter.StringHttpMessageConverter"/> <!– FastJsonHttpMessageConverter4 使@ResponseBody支持返回Map<String,Object>等类型,它会自动转换为json–> <!– 需要返回json时需要配置 produces = "application/json"。不需要再指定utf-8了 –> <bean id="fastJsonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <!– 加入支持的媒体类型 –> <property name="supportedMediaTypes"> <list> <!– 这里顺序不能反,一定先写text/html,不然IE执行AJAX时,返回JSON会出现下载文件 –> <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>
<?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实体类
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格式,传给页面。 * 前提是,需要有jackson,jar包的依赖(通过注解方式,就不需要在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原理: