SSM学习笔记
maven
什么是maven
项目管理工具
pom
mybatis参数
## 单个javabean
默认通过书信值引用。
多个参数
Girl queryByNameFlower(@Param("name") String name,@Param("flower") String flower);
<!--SELECT * FROM girl WHERE name = #{param1} AND flower = #{param2}-->
<!--SELECT * FROM girl WHERE name = #{arg0} AND flower = #{arg1}-->
SELECT * FROM girl WHERE name = #{name} AND flower = #{flower}
map
Map<String,Object> map = new HashMap<>();
map.put("name","he");
map.put("flower","flowerLi");
sql语句中直接用名称取值
多个javabean
类似于多个参数,只不过参数变成了对象
一组值的传入(List集合)
SQL标签
<!--foreach
collection 描述集合
open 以什么拼接符号开头
close 以什么结尾
item 一个数据项的代号
separator item之间的分隔符
index 如需使用标号,也可使用
-->
<!--使用where标签,使得语法合法,
自动消除多余的and,只能处理前置的and。
if标签里有多个条件,则用and连接。
-->
<!--例如:传入非空值是修改,否则不修改.
set标签纠正语法,去掉后置的多余逗号。
-->
trim标签
<trim prefix="where" suffixOverrides="and">
<if test="city != null">
CITY = #{city} AND
</if>
<if test="country != null">
COUNTRY = #{country} AND
</if>
</trim>
解决字符串拼接问题
1.可用sql函数
select * from address
where
city like concat('%',#{city},'%')
2.bind标签
<bind name="_city" value="'%'+city+'%'"/>
select * from address
where
city like #{_city}
sql标签
<sql id="baseCoulmn">
city,country,state
</sql>
select <include refid="baseCoulmn"/>
from address
cach缓存
默认情况下,一级缓存是开启的,且无法关闭。
一级缓存是单个会话级别的
- 如果关闭会话,缓存失效。
- 如果会话过程有增删改操作,则缓存失效。
- java中 sqlSession.clearCache();清掉所有缓存
二级缓存是多个会话级别的
<setting name="cacheEnabled" value="true">
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
多表查询映射
<resultMap id="rMap" type="javaClass">
<id property="id" column="id"/>
<result property="id" column="id"/>
<association property="\\class" javaType="">
<result property="" column=""/>
</association>
</resultMap>
<!--
collection标签用来描述集合
ofType是描述集合里的一个元素的类型
-->
List<Comment> comments;
<collection property="comments"
ofType="self.he.pojo.Comment">
<id property="id" column="cid"/>
<result property="content" column="commentContent"/></collection>
spring
- 添加spring依赖
- 编写spring的配置文件
- 通过spring应用程序上下文获取对象
1.依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.4.RELEASE</version>
</dependency>
2.配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<!--将对象的创建-交给spring容器,
在配置文件里声明需要的对象。
class:Java类的全限定名
id: 此对象的昵称方便区分-->
<bean class="self.he.pojo.Girl" id="girl">
</bean>
</beans>
3.java代码
public class Girl {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
public void m1(){
//获取上下文对象,spring里面声明对象都需要通过上下文获取
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过此对象获取girl
Girl g = (Girl) ctx.getBean("girl");
System.out.println(g);
}
核心内容
- IOC
- AOP
IOC
概念:控制反转。
将对象的创建交给Spring容器。
值的注入:
-
setter注入(最常用)
-
必须有setter方法,如:name setName()
-
用property标签注入
<bean class="self.he.pojo.PrettyGirl" id="girl"> <property name="name" value="王妃"/> </bean>
-
-
非字面值的注入问题:使用ref指向另一个bean
<bean class="self.he.pojo.Dog" id="dog"> <property name="name" value="汪汪"/> </bean> <bean class="self.he.pojo.PrettyGirl" id="girl"> <property name="dog" ref="dog"/> </bean>
-
String[]
<property name="friends"> <array> <value>钰子</value> <value>雨子</value> <value>呀子</value> </array> </property>
-
List<>
<property name="nums"> <list> <value>1</value> <value>3</value> <value>4</value> </list> </property>
-
set<>
-
<property name="grils"> <set> <bean class="self.he.pojo.Girl"> <property name="age" value="18"/> <property name="name" value="Li"/> </bean> <bean class="self.he.pojo.Girl"> <property name="age" value="11"/> <property name="name" value="She"/> </bean> </set>
Map<>
<property name="goddessMap"> <map> <entry key="Li"> <bean class="self.he.pojo.Goddess"> <property name="name" value="Li"/> <property name="hair" value="Red"/> </bean> </entry> <entry key="Di"> <bean class="self.he.pojo.Goddess"> <property name="name" value="Di"/> <property name="hair" value="Black"/> </bean> </entry> </map> </property>
-
-
构造器注入
-
默认使用无参构造器
-
constructor-arg标签
<bean class="self.he.pojo.Cat" id="girl"> <constructor-arg name="name" value="Li"/> <constructor-arg name="color" value="red"/> </bean>
-
bean标签的探讨:
- abstract:抽象
- parent:继承bean标签
- destory-method: 这个bean销毁是执行的方法。容器close(),refresh()
- init-method: 初始化时使用的方法。
- scope:指定范围
- singleton:单例,spring上下文
- prototype:原型
- lazy-init: true使用时初始化。
- depends-on: 依赖bean,如果bean的使用严重依赖于另一个bean。
alias标签:
-
注入别名
<alias name="dog" alias="gdog"/>
-
自动注入,autowire属性
-
byType
-
byName
-
constructor:根据构造器的参数名去匹配bean。
-
no
<!--byType 在上下文中,根据类型寻找cat 中的属性 girl,并以赋值,有且只有一个,否则报错--> <bean class="self.he.pojo.Cat" id="cat" autowire="byType"> <property name="name" value="佩奇"/> <property name="color" value="pik"/> </bean> <bean class="self.he.pojo.Girl"> <property name="name" value="Li"/> <property name="age" value="18"/> </bean> <bean class="self.he.pojo.Cat" id="girl"> <constructor-arg name="name" value="Li"/> <constructor-arg name="color" value="red"/>
resource
-
Xml文件里引入其他properties文件:
<context:property-placeholder location="classPath:xxx.properties"/> <!--用表达式${}去引用properties的属性的值,-->
-
一个配置文件引入其他配置文件:classPath的根目录是resource目录
<import resource="classPath:xxx.xml"/>
常用注解
xml中要激活注解:
<context:component-scan base-package="self.he"/>
- component
- controller
- service
- repository
- autowired自动注入
AOP
概念
面向切面编程。
依赖包:
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1 aop是基于代理完成的,所以要激活自动代理-->
<aop:aspectj-autoproxy/>
<!--2 注册切面-->
<bean class="self.he.advice.BeforeAdvice" id="beforeAdvice">
</bean>
<!--3 配置切入点等信息-->
<aop:config>
<aop:aspect id="beforeAspect" ref="beforeAdvice">
<!--aop:before 表明前置通知
method:指明使用哪个方法切
pointcut:切入点
包,类,方法
-->
<aop:before method="methodBefore" pointcut="execution(* self.he.service.ProviderService.*(..))"></aop:before>
</aop:aspect>
</aop:config>
<bean class="self.he.service.ProviderService"
id="providerService"></bean>
</beans>
execution()表达式:
例如:execution(* self.he.service.ProviderService.*(..))
测试
@Test
public void m1(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
//不是spring管理的bean,织入无效。
ProviderService providerService = new ProviderService();
providerService.add();
ProviderService providerService1 = ctx.getBean("providerService", ProviderService.class);
providerService1.add();
}
返回执行:after-returning
<aop:after-returning method="AfterReturn" returning="returning" pointcut="execution(* self.he.service.HelloService.*(..))"/>
注解模式
xml文件
<!--1 自动代理-->
<aop:aspectj-autoproxy/>
<!--2 配置自动扫描包-->
<context:component-scan base-package="self"/>
切面:
@Aspect//标记为一个切面
@Component//标记为一个组件,相当于在xml中注册一个bean
public class BeforeAdvice {
@Before("execution(* self.she.service.HelloService.hello(String,String))")
//获取方法名,参数
public void before(JoinPoint joinPoint){
System.out.println("before!!!!!"+joinPoint.getSignature().getName()+ Arrays.toString(joinPoint.getArgs()));
}
@Before("execution(* self..*.*(..))")
public void before2(){
System.out.println("before2!!!");
}
}
切点:
@Component
public class HelloService {
public void hello(String name,String sex){
System.out.println("hello "+name+"!"+sex+"!!!");
}
public String eat(){
System.out.println("eating!!!!");
return "Li";
}
}
注解方式获得bean
配置类
@Configuration
@ComponentScan(value = "self.she")
public class SpringConfig {
@Bean("girl")
public Girl creatGirl(){
Girl girl = new Girl();
girl.setName("Li");
return girl;
}
}
测试:
@Test
public void m1(){
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
Girl girl = ctx.getBean("girl",Girl.class);
System.out.println(girl.getName());
}
springMVC
简介
springMVC是一个web层的框架。
model 模型
view 视图
controller 控制器
一种设计模式,将责任进行拆分,不同组件负责不同功能。
好处:
- 结构清晰
- 更好维护
坏处:
- 更加复杂
入门体验
1.创建web项目
2.编写web.xml,注册一个特殊的servlet,前端控制器
3.编写一个springMVC的配置文件
- 注册一个视图解析器
4.编写一个控制器
5.编写一个结果页面
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_3_1.xsd"
version="3.1">
<!--注册一个前端控制器-->
<servlet>
<!--这里名字有讲究,
如果不修改spring配置文件的默认位置,那么springmvc
会去web-inf下找一个springmvc-servlet.xml的文件-->
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<!--servlet映射配置-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--统一写/-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
pom.xml:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.4.RELEASE</version>
</dependency>
控制器代码:
package self.he.controller;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloController implements Controller {
@Nullable
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mav = new ModelAndView();
mav.addObject("girl","Li");
mav.setViewName("girl");
return mav;
}
}
视图代码:
<%--
Created by IntelliJ IDEA.
User: he
Date: 2019/2/13
Time: 16:19
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${girl}
</body>
</html>
解释分析
web.xml
注册前端控制器,目的让springmvc去处理请求
<!--servlet映射配置-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--统一写/-->
<url-pattern>/</url-pattern>
</servlet-mapping>
url-pattern的写法问题:
- /
- /* (永远不要这样写,请求helloController时,过去后视图为girl.jsp,又将girl.jsp作为请求再去访问controller)
- *.do
springMVC配置文件名
web.xml
默认情况下使用dispatcherServlet的名字作为命名空间
[servlet-name]-servlet.xml (WEB-INF)下寻找
[servlet-name]-servlet=namespace
<servlet>
<!--这里名字有讲究,
如果不修改spring配置文件的默认位置,那么springmvc
会去web-inf下找一个springmvc-servlet.xml的文件-->
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--重新命名配置文件名-->
<init-param>
<param-name>namespace</param-name>
<param-value>mvc</param-value>
</init-param>
</servlet>
配置文件默认在WEB-INF下,但是maven项目要求在resources目录下。
解决:重新指定上下文位置即可web.xml
<init-param>
<!--上下文配置的位置的指定-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:mvc.xml</param-value>
</init-param>
此时在类路径下寻找mvc.xml
视图解析器
springMVC支持多种视图技术
- jsp
- freemaker(模板技术)
内部的资源视图解析器
-
视图前缀
-
/jsp/ 请求响应的资源路径配置
viewName:girl /jsp/girl
-
-
后缀
- .jsp 此时前缀+视图名+后缀 = /jsp/girl.jsp
注解开发模式
基本注解;
- @Controller
- @RequestMapping
开发步骤
1.配置注解扫描包
<!--配置注解扫描包-->
<context:component-scan base-package="self.he.controller"/>
<!--配置一个视图解析器
常用内部资源视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--1 前缀-->
<property name="prefix" value="/jsp/"/>
<!--2 后缀-->
<property name="suffix" value=".jsp"/>
</bean>
2.在指定类上添加@Controller注解
3.添加@RequestMapping
@Controller//不需要继承任何类
@RequestMapping("/bye")
public class ByeController {
@RequestMapping("/bye")
public String bye(Model model){
model.addAttribute("model","Li");
// return的是ViewName
//此时去的/jsp/bye.jsp
return "bye";
}
@RequestMapping("/goodBye")
public String goodBye(Model model){
model.addAttribute("model","Lily");
return "bye";
}
}
list 问题
导入依赖
<!--jstl依赖-->
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
controller:
@RequestMapping("/byeBye")
public String byeBye(Model model){
List<People> list = new ArrayList<>();
People p1 = new People();
p1.setName("Li");
p1.setSex("girl");
People p2 = new People();
p2.setName("He");
p2.setSex("boy");
list.add(p1);
list.add(p2);
model.addAttribute("model",list);
return "byeBye";
}
jsp:
<c:forEach items="${model}" var="obj">
<tr>
<td>${obj.name}</td>
<td>${obj.sex}</td>
</tr>
</c:forEach>
转发与重定向
-
转发到页面
-
重定向到另一个页面redirect:path
@RequestMapping("redirect") public String redirect(Model model){ model.addAttribute("model","hello"); return "redirect:/jsp/redirect.jsp"; }
-
转发到另一个控制器forward:path
// 模拟请求 @RequestMapping("/request") public String request(WebRequest request){ System.out.println(request.getParameter("girl")); return "forward"; }
@RequestMapping
- @RequestMapping("/m1")
- value 写的是路径,是一个数组的形式,可匹配多个路径,path与 value对等
- @RequestMapping(value={"m1","m2"})
- method 指定接收的请求类型,如果没写就所有类型都接收
- @RequestMapping(value={"m1","m2"}, method= RequestMethod.GET)
- params 可以指定参数
- @RequestMapping(value="/m1",params={"girl","boy"})
- 可以指定值params={"girl=王妃","boy!=爱卿"}
- header 能够影响浏览器的行为
- consumers 消费者,媒体类型,可以限定必须为application/json;chartset=UTF-8
- produces 产生的响应的类型
请求路径的问题
Springmvc支持的ant风格
@RequestMapping("/Li?")
- ?任意的字符,斜杠除外
- *表示0-n,任意个字符都行,斜杠除外
- /** 支持任意层路径
@GetMapping,@PostMapping.....
- getMapping 只限定了get请求
- postMapping 只限定了post请求
对于非get post请求的支持
需要有额外的内容添加,要增加一个过滤器来处理。
过滤器:
<!--注册一个支持所有http请求类型的过滤器-->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
表单还要添加隐藏参数;
delete
<form action="${ctx}/he/m1" method="post">
<input type="hidden" name="_method" value="DELETE"/>
<input type="submit" value="提交"/>
</form>
关于静态资源访问的问题
用于在web.xml中设置了servlet的url匹配方式为/ ,所以静态资源也当做一个后台请求。
解决方式:
1.交给默认servlet处理。不让DispatcherServlet处理。
在mvc配置文件中加
<!--默认servlet处理者,识别MIME类型-->
<!--默认servlet处理者,只加它注解会失效-->
<mvc:default-servlet-handler/>
<!--重新激活注解模式-->
<mvc:annotation-driven/>
2.通过映射关系描述
<mvc:resources mapping="/static/css/*" location="static/css/"/>
3.在web.xml定义映射规则
@PathVariable
路径变量。
@RequestMapping("/add/{name}/{sex}")
public String addPeople(@PathVariable("name") String name,@PathVariable("sex")String sex){
System.out.println(name+":"+sex);
return "forward";
}
@Responsebody
返回数据,一般情况下返回json格式数据。
@PutMapping("/put")
@ResponseBody//需要额外的json包的支持
public String putPeople(String name){
System.out.println(name+":");
// Map<String,String> map = new HashMap<>();
// map.put("msg","ok");
return "ok";
}
@RequestBody
json数据,不是通过form表单传递
ajax({
data:
} )
@SessionAttributes
用在类上面,将模型自动填充到会话里去。
@Controller
@RequestMapping("/people2")
@SessionAttributes("people")
public class People2Controller {
@RequestMapping("/login3")
public String login3(@ModelAttribute People people) {
System.out.println(people.getName());
return "redirect:/jsp/login.jsp";
}
}
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${sessionScope.people.name}
</body>
</html>
@SessionAttribute
要求当前会话里必须要有某个对象。
public String login3(@SessionAttribute People people) {
System.out.println(people.getName());
return "redirect:/jsp/login.jsp";
}
关于post请求中文乱码问题
添加过滤器,springmvc提供过滤器。
<!--指定编码,这段配置要放在所有filter的最前面,否则会不生效-->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
关于form表单提交数据方式
方式一:通过属性名绑定
put people
<form action="${ctx}/people/put" method="post">
<input type="hidden" name="_method" value="put"/>
<input type="text" name="name"/><br>
<input type="password" name="sex"/><br>
<input type="submit" value="提交"/>
</form>
@PutMapping("/put")
@ResponseBody//需要额外的json包的支持
public String putPeople(String name,String sex){
System.out.println(name+":"+sex);
// Map<String,String> map = new HashMap<>();
// map.put("msg","ok");
return "ok";
}
方式二:@RequestParam()
@PutMapping("/put")
@ResponseBody//需要额外的json包的支持
public String putPeople(@RequestParam("name")String name,@RequestParam("sex")String sex){
System.out.println(name+":"+sex);
// Map<String,String> map = new HashMap<>();
// map.put("msg","ok");
return "ok";
}
方式三:直接用pojo形式
@PutMapping("/put")
@ResponseBody//需要额外的json包的支持
public String putPeople(People people){
System.out.println(people.getName()+":"+people.getSex());
return "ok";
}
关于表单提交date类型数据问题
put people and date
<form action="${ctx}/people/date" method="post">
<input type="date" name="date"/><br>
<input type="submit" value="提交"/>
</form>
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
@PostMapping("/date")
@ResponseBody//需要额外的json包的支持
public String postPeople(People people){
System.out.println("hhhh");
System.out.println(people.getDate());
return "ok";
}
2.在属性上添加注解
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date;
@ModelAttribute可解决页面间数据交换
使用方式一:
//在controller里任意一个方法执行前执行
@ModelAttribute
public People init(){
System.out.println("init........");
People people = new People();
people.setName("Li");
return people;
}
@RequestMapping("/login")
public String login(Model model){
System.out.println(model.containsAttribute("people"));
return "forward";
}
方法二:
@ModelAttribute("people")
public void init(Model model){
System.out.println("init........");
People people = new People();
people.setName("Li");
model.addAttribute("people",people);
}
方法三:
如果请求页面传了people则使用请求的值,如果没有则使用默认的。
可用于页面间数据交换。
@RequestMapping("/login2")
public String login2(@ModelAttribute People people){
System.out.println(people.getName());
return "login";
}
post people to other page
<form action="${ctx}/people2/login2" method="post">
<input type="text" name="name"/><br>
<input type="password" name="sex"/><br>
<input type="submit" value="提交"/>
</form>
后台传json给前端
1.导入json解析依赖
<!--json依赖-->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version>
</dependency>
2.利用@ResponseBody
@RequestMapping("m1")
@ResponseBody
public People m1(){
People people = new People();
people.setName("Li");
people.setSex("girl");
people.setDate(new Date());
return people;
}
前台解析json:
<script>
$(function () {
$("#b").click(function () {
$.ajax({
url:'${ctx}/json/m1',
type:'post',
success:function (data) {
alert(data.name+":"+data.sex)
}
})
})
})
</script>
前台ajax给后台传json
注意 contentType:'application/json',不可缺
$("#bb").click(function () {
var obj={
'name':'Li 李',
'sex':'girl'
};
$.ajax({
url:'${ctx}/json/m2',
type:'post',
contentType:'application/json',
data:JSON.stringify(obj),
success:function (data) {
alert(data.name);
}
})
})
后台用注解@RequestBody接收
//接收前台传来的json
@RequestMapping("/m2")
@ResponseBody
public People m1(@RequestBody People people){
System.out.println(people.getName());
People people = new People();
people.setName("Li");
people.setSex("girl");
people.setDate(new Date());
return people;
}
@RestController=@Controller+@ResponseBody
xml解析传输
很多第三方开发会使用xml传输数据,例如:微信
1.添加xml依赖
<!--xml依赖-->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.9.8</version>
</dependency>
2.@RequestMapping
@RequestMapping(value = "/m1",produces ={MediaType.APPLICATION_XML_VALUE})
@ResponseBody
public People m1(){
People people = new People();
people.setName("Lily");
people.setSex("girl");
people.setDate(new Date());
return people;
}
文件上传
1.加入依赖
<!--Apache文件上传依赖-->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
2.在springmvc配置文件中注册文件上传解析器
<!--文件上传解析器,
id="multipartResolver"只能是这个,源代码规定的
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--定义最大文件上传大小,byte-->
<property name="maxUploadSize" value="1024000"/>
<!--指定上传的编码-->
<property name="defaultEncoding" value="UTF-8"/>
<!--单个文件最大大小-->
<property name="maxUploadSizePerFile" value="200000"/>
</bean>
3.上传页面
<%--
Created by IntelliJ IDEA.
User: he
Date: 2019/2/15
Time: 9:39
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
单文件提交:
<form action="${ctx}/file/upload" method="post" enctype="multipart/form-data">
文件:<input type="file" name="file"/><br>
<input type="submit" value="提交">
</form>
<br>
多文件提交:
<form action="${ctx}/file/upload2" method="post" enctype="multipart/form-data">
文件1:<input type="file" name="file"/><br>
文件2:<input type="file" name="file"/><br>
文件3:<input type="file" name="file"/><br>
文件4:<input type="file" name="file"/><br>
<input type="submit" value="提交">
</form>
</body>
</html>
4.响应控制类
private static String uploadPath = "E:"+ File.separator;
@RequestMapping("/upload")
public String upload(@RequestParam("file")MultipartFile multipartFile, Model model){
//1.传到哪里去。2.数据 3.传的细节
if (multipartFile != null && !multipartFile.isEmpty()){
//不空再传
//1.获得文件名
String originalFilename = multipartFile.getOriginalFilename();
//2.截取文件名前缀
String fileNamePrefix = originalFilename.substring(0,originalFilename.lastIndexOf('.'));
//3.构建新文件名 前缀+时间戳
String newFilePrefix = fileNamePrefix+new Date().getTime();
//4.得到新文件名
String newFileName =newFilePrefix+originalFilename.substring(originalFilename.lastIndexOf('.'));
//5.构建文件对象
File file = new File(uploadPath+newFileName);
//6.写入文件
try {
multipartFile.transferTo(file);
model.addAttribute("fileName",newFileName);
} catch (IOException e) {
e.printStackTrace();
}
}
return "uploadSuc";
}
@RequestMapping("/upload2")
public String upload2(@RequestParam("file") MultipartFile[] multipartFiles,Model model){
List<String> fileNames = new ArrayList<>();
System.out.println(multipartFiles != null && multipartFiles.length >0);
if (multipartFiles != null && multipartFiles.length >0){
for (MultipartFile multipartFile:multipartFiles) {
if (multipartFile != null && !multipartFile.isEmpty()){
//不空再传
//1.获得文件名
String originalFilename = multipartFile.getOriginalFilename();
//2.截取文件名前缀
String fileNamePrefix = originalFilename.substring(0,originalFilename.lastIndexOf('.'));
//3.构建新文件名 前缀+时间戳
String newFilePrefix = fileNamePrefix+new Date().getTime();
//4.得到新文件名
String newFileName =newFilePrefix+originalFilename.substring(originalFilename.lastIndexOf('.'));
//5.构建文件对象
File file = new File(uploadPath+newFileName);
//6.写入文件
try {
multipartFile.transferTo(file);
fileNames.add(newFileName);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
model.addAttribute("fileNames",fileNames);
return "uploadSuc";
}
文件下载
@RequestMapping("/down")
public void fileDown(HttpServletResponse response){
//通过输出流写入客户端
// response.setCharacterEncoding("UTF-8");
//1.获取下载文件名
String fileName = "哈哈.jpg";
//2.构建一个文件对象,通过Paths工具类获得Path对象
Path path = Paths.get(uploadPath,fileName);
//3.判断它是否存在
if(Files.exists(path)){
//存在则下载
//4.设定response的响应类型
//获取文件后缀
String fileSuffix = fileName.substring(fileName.lastIndexOf('.')+1);
//设置contentType
response.setContentType("application/"+fileSuffix);
try {
//ISO8859-1编码
response.addHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes("UTF-8"),"ISO8859-1"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(fileSuffix);
//5 通过Path写出去
try {
Files.copy(path,response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意事项: //ISO8859-1编码
response.addHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes("UTF-8"),"ISO8859-1"));
避免中文无法识别
拦截器
通过实现HandlerInterceptor
- 前置处理
- 后置处理
- 完成处理
案例:
登录请求拦截,如果session有user,不拦截,没有则拦截,但/user/login不拦截。
1.拦截类
package self.he.interceptors;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import self.he.pojo.User;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SessionInterceptor implements HandlerInterceptor{
private static final Logger LOGGER = Logger.getLogger(SessionInterceptor.class);
//检查当前会话是否有User,有则放行,没有则拦截
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object user = request.getSession().getAttribute("SESSION_USER");
if(user == null){
LOGGER.warn("没有权限,请先登录!");
return false;
}
if(user instanceof User){
//查数据库检查
User u = (User)user;
u.setPwd(null);
request.getSession().setAttribute("SESSION_USER",u);
LOGGER.info(u.getName()+"会话中。。");
return true;
}else {
LOGGER.warn("不要搞事,请先登录!");
return false;
}
}
}
2.配置拦截器
<!--拦截器配置-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**/*"/>
<bean class="self.he.interceptors.MethodTimerInterceptor">
</bean>
</mvc:interceptor>
<mvc:interceptor>
<!-----------------------------------------------
拦截user下的,但login除外
-->
<mvc:mapping path="/user/**/*"/>
<mvc:exclude-mapping path="/user/login"/>
<bean class="self.he.interceptors.SessionInterceptor">
</bean>
</mvc:interceptor>
</mvc:interceptors>
控制类:
package self.he.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import self.he.pojo.User;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/login")
public String login(User user, HttpSession session){
if(user != null&& user.getName()!= null && user.getName().equals("Li")){
//(数据库检查)
session.setAttribute("SESSION_USER",user);
return "user";
}
System.out.println("....login...........");
return "redirect:/login.jsp";
}
@RequestMapping("/delete")
public String delete(){
System.out.println("....可以为所欲为了delete...........");
return "user";
}
}
拦截器执行顺序问题
有N个拦截器,都能拦截同一个URI时,执行顺序:
在springmvc配置中配置的顺序有关。配置在前的先执行。
前置处理与后置处理顺序刚好相反。