ResponseBody和RequestBody
@ResponseBody把后台pojo转换json对象,返回到页面。
@RequestBody接受前台json数据,把json数据自动封装javaBean
请求和响应都是json数据
导入jar包
在DispatcherServlet-servlet.xml中添加个json转换器
写个jsp页面,提交json请求参数
后台处理
Springmvc多视图
多视图是一个方法可以返回json/xml等格式的数据
导入xml格式支持的jar包
配置支持多视图
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<!-- 配置支持媒体类型 -->
<property name="contentNegotiationManager">
<bean class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json"></entry>
<entry key="xml" value="application/xml"></entry>
</map>
</property>
</bean>
</property>
<!-- 指定默认视图 -->
<property name="defaultViews">
<!-- 支持多个视图 -->
<list>
<!-- 对josn格式视图支持 -->
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
<!-- xml格式视图支持 -->
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.gyf.backoffice.domain.Student</value>
</list>
</property>
</bean>
</constructor-arg>
</bean>
</list>
</property>
</bean>
控制器提供一个接口
测试
Spring + SpringMVC + Mybatis整合
导入jar包
在项目目录下创建config目录,在其中创建springMVC.xml
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<!-- 1.配置注解扫描位置 -->
<context:component-scan base-package="com.gyf.backoffice.web.controller" />
<!-- 2.配置注解处理映射-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--3.配置适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
</bean>
<!-- 4.配置springmvc视图解析器 视图解析器解析的视频路径为:前缀 + 后缀 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
在web.xml添加springmvc配置
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 3.0的springmvc 默认加载WEB-INF下的dispatcher-servlet.xml文件 3.2的springmvc
加载DispatcherServlet-servlet.xml文件 -->
<init-param>
<!-- 修改黑底springmvc加载的配置文件路径 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
先配置一个Controller跑出一个页面
导入逆向工程生成JavaBean/Mapper
修改ItemsMapper.java和ItemsMapper.xml增加一个查询所有数据的功能
定义Service层接口并实现
配置mybatis.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 别名配置 -->
<typeAliases>
<!-- 批量配置别名:指定批量定义别名的类包,别名为类名(首字母大小写都可) -->
<package name="com.gyf.backoffice.domain"/>
</typeAliases>
<mappers>
<!-- 批量加载映射文件 -->
<package name="com.gyf.backoffice.mapper"/>
</mappers>
</configuration>
创建spring的applicaiontContext.xml
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<!-- 1.加载db配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 2.配置c3p0数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="2"/>
</bean>
<!-- 3.让spring管理sqlsessionFactory -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 指定配置文件位置 -->
<property name="configLocation" value="classpath:mybatis.xml"/>
</bean>
<!-- 4.配置mapper扫描器.批量扫描创建代理对象 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.gyf.backoffice.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
</bean>
</beans>
db.properties数据库配置信息
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456
Web.xml配置spring容器
<!-- spring的配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
applicationContext.xml添加bean的注解装配
<!-- 配置扫描注解 -->
<context:component-scan base-package="com.gyf.backoffice"/>
ItemsService
ItemsController
这里可以方法items/list.do,是否可以获取数据
applicationContext.xml事务配置
<!-- 5.配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 6.开启事务注解-->
<tx:annotation-driven></tx:annotation-driven>
添加一个保存方法测试事务
显示商品数据
Controller.java
Views/items/list.jsp
效果:
删除商品
service
controller
显示编辑商品页面
controller
Edit.jsp
效果
更新商品
需要在页面中隐藏一个input标签存id
解决乱码,在web.xml配置
<!-- 配置编码过滤器 -->
<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>
controller
Service:需要改下逻辑
文件上传
导包
Springmvc.xml配置支持文件上传
Html/JS
后台
@Controller
@RequestMapping("upload")
public class UploadController {
@RequestMapping("itemsPic")
public void itemsPic(HttpServletRequest request,String fileName, PrintWriter writer) throws Exception{
MultipartHttpServletRequest mulRequest = (MultipartHttpServletRequest) request;
//通过字段名获取文件数据
MultipartFile file1 = mulRequest.getFile(fileName);
System.out.println(fileName + ":上传文件大小 " + file1.getSize());
//格式化文件名
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
String saveName = sdf.format(new Date());
Random rd = new Random();
for(int i=0;i<3;i++){
saveName += rd.nextInt(10);//添加三个随机数
}
//文件后缀名
String suffix = file1.getOriginalFilename().split(".")[1];
String saveFileName = saveName + "." + suffix;
//文件保存目录
String dir = request.getServletContext().getRealPath("/upload");
File dirFile = new File(dir);
if(dirFile.exists() == false)dirFile.mkdirs();
//文件保存路径
String relativePath = "/upload/" + saveFileName;
String totalPath = request.getServletContext().getRealPath(relativePath);
System.out.println(totalPath);
File newFile = new File(totalPath);
//保存
FileCopyUtils.copy(file1.getInputStream(), new FileOutputStream(newFile));
Thread.sleep(2000);
//file1.transferTo(newFile);
//返回一个相对路径 相对路径和全路径
String serverIp = "http://127.0.0.1:8080" + request.getServletContext().getContextPath();
String respJson = "{"imgUrl":"" + serverIp + relativePath+""}";
writer.write(respJson);
}
}
Oscache页面缓存
导包
测试
缓存的作用域(不同浏览器缓存的时间不同)
如果scope是application,不同浏览器访问同一个路径时,时间是一样的
缓存刷新时间
固定存储的Key
缓存持久化
创建oscache.properties这个配置文件必须在classpath下面:
cache.memory=false
cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener
cache.path=C:test
访问路径后会在test的application中创建缓存文件
Oscache整合ssm项目
商品页面访问量特别大,给商品页面缓存。Items路径下所有请求都缓存。
在web.xml中配置页面缓存
<!-- 配置页面缓存 -->
<filter>
<filter-name>oscache</filter-name> <filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>
<init-param>
<param-name>time</param-name>
<param-value>3600</param-value>
</init-param>
<init-param>
<param-name>scope</param-name>
<param-value>application</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>oscache</filter-name>
<url-pattern>/items/*</url-pattern>
</filter-mapping>
第一次访问Items下面的页面,控制器方法会执行,第二次就走缓存页面
Springmvc整合freemarker
FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本
导包
Springmvc配置freemark
<!-- 配置freemarker -->
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/views" />
<property name="defaultEncoding" value="UTF-8"></property>
</bean>
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="contentType" value="text/html;charset=utf-8"/>
<property name="suffix" value=".ftl" />
</bean>
写一个hello.ftl模板
ItemsController
测试结果
list.jsp改成list.ftl
<html>
<head>
<title>Title</title>
</head>
<body>
商品:<br>
<table border="1">
<tr>
<td>名称</td>
<td>价格</td>
<td>描述</td>
<td>日期</td>
<td>操作</td>
</tr>
<#list itemsList as items>
<tr>
<td>${items.name}</td>
<td>${items.price}</td>
<td>${items.detail}</td>
<td>${items.createtime?string("yyyy-MM-dd HH:mm:ss zzzz")}</td>
<td>
<a href="/items/delete.do?id=${items.id}">删除</a>
<a href="/items/edit.do?id=${items.id}">编辑</a>
</td>
</tr>
</#list>
</table>
</body>
</html>
SpringMVC的拦截器
Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理
登录拦截器
public class LoginInterceptor implements HandlerInterceptor{
//controller执行后且视图返回后调用此方法
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("返回视图前 后处理");
}
//controller执行后但未返回视图前调用此方法
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("未返回视图前 后处理....");
}
// controller执行前调用此方法
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
// TODO Auto-generated method stub
System.out.println("预处理....");
//如果是登录页面则放行
if(request.getRequestURI().indexOf("login.do")>=0){
return true;
}
HttpSession session = request.getSession();
//如果用户已登录也放行
if(session.getAttribute("user")!=null){
return true;
}
//用户没有登录挑战到登录页面
request.getRequestDispatcher("/WEB-INF/views/login.jsp").forward(request, response);
return false;
}
}
登录控制器
登录界面
登录拦截器配置