maven
什么是maven
项目管理工具
pom
mybatis参数
## 单个javabean
默认通过书信值引用。
多个参数
Girl queryByNameFlower(@Param("name") String name,@Param("flower") String flower);
SELECT * FROM girl WHERE name = #{name} AND flower = #{flower}
map
Map map = new HashMap<>();
map.put("name","he");
map.put("flower","flowerLi");
sql语句中直接用名称取值
多个javabean
类似于多个参数,只不过参数变成了对象
一组值的传入(List集合)
SQL标签
trim标签
CITY = #{city} AND
COUNTRY = #{country} AND
解决字符串拼接问题
1.可用sql函数
select * from address
where
city like concat('%',#{city},'%')
2.bind标签
select * from address
where
city like #{_city}
sql标签
city,country,state
select
from address
cach缓存
默认情况下,一级缓存是开启的,且无法关闭。
一级缓存是单个会话级别的
- 如果关闭会话,缓存失效。
- 如果会话过程有增删改操作,则缓存失效。
- java中 sqlSession.clearCache();清掉所有缓存
二级缓存是多个会话级别的
多表查询映射
List comments;
spring
- 添加spring依赖
- 编写spring的配置文件
- 通过spring应用程序上下文获取对象
1.依赖
org.springframework
spring-context
5.1.4.RELEASE
2.配置文件
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标签注入
-
非字面值的注入问题:使用ref指向另一个bean
-
String[]
钰子 雨子 呀子 -
List<>
1 3 4 -
set<>
-
Map<>
-
构造器注入
默认使用无参构造器
constructor-arg标签
bean标签的探讨:
- abstract:抽象
- parent:继承bean标签
- destory-method: 这个bean销毁是执行的方法。容器close(),refresh()
- init-method: 初始化时使用的方法。
- scope:指定范围
- singleton:单例,spring上下文
- prototype:原型
- lazy-init: true使用时初始化。
- depends-on: 依赖bean,如果bean的使用严重依赖于另一个bean。
alias标签:
注入别名
自动注入,autowire属性
byType
byName
constructor:根据构造器的参数名去匹配bean。
no
resource
Xml文件里引入其他properties文件:
一个配置文件引入其他配置文件:classPath的根目录是resource目录
常用注解
xml中要激活注解:
- component
- controller
- service
- repository
- autowired自动注入
AOP
概念
面向切面编程。
依赖包:
org.aspectj
aspectjrt
1.9.2
org.aspectj
aspectjweaver
1.9.2
配置文件
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
注解模式
xml文件
切面:
@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:
springmvc
org.springframework.web.servlet.DispatcherServlet
springmvc
/
pom.xml:
org.springframework
spring-webmvc
5.1.4.RELEASE
控制器代码:
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" %>
Title
${girl}
解释分析
web.xml
注册前端控制器,目的让springmvc去处理请求
springmvc
/
url-pattern的写法问题:
- /
- /* (永远不要这样写,请求helloController时,过去后视图为girl.jsp,又将girl.jsp作为请求再去访问controller)
- *.do
springMVC配置文件名
web.xml
默认情况下使用dispatcherServlet的名字作为命名空间
[servlet-name]-servlet.xml (WEB-INF)下寻找
[servlet-name]-servlet=namespace
springmvc
org.springframework.web.servlet.DispatcherServlet
namespace
mvc
配置文件默认在WEB-INF下,但是maven项目要求在resources目录下。
解决:重新指定上下文位置即可web.xml
contextConfigLocation
classpath:mvc.xml
此时在类路径下寻找mvc.xml
视图解析器
springMVC支持多种视图技术
- jsp
- freemaker(模板技术)
内部的资源视图解析器
-
视图前缀
-
/jsp/ 请求响应的资源路径配置
viewName:girl /jsp/girl
-
-
后缀
- .jsp 此时前缀+视图名+后缀 = /jsp/girl.jsp
注解开发模式
基本注解;
- @Controller
- @RequestMapping
开发步骤
1.配置注解扫描包
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 问题
导入依赖
javax.servlet
jstl
1.2
controller:
@RequestMapping("/byeBye")
public String byeBye(Model model){
List 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:
${obj.name}
${obj.sex}
转发与重定向
转发到页面
-
重定向到另一个页面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请求的支持
需要有额外的内容添加,要增加一个过滤器来处理。
过滤器:
hiddenHttpMethodFilter
org.springframework.web.filter.HiddenHttpMethodFilter
hiddenHttpMethodFilter
/*
表单还要添加隐藏参数;
delete
关于静态资源访问的问题
用于在web.xml中设置了servlet的url匹配方式为/ ,所以静态资源也当做一个后台请求。
解决方式:
1.交给默认servlet处理。不让DispatcherServlet处理。
在mvc配置文件中加
2.通过映射关系描述
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 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" %>
Title
${sessionScope.people.name}
@SessionAttribute
要求当前会话里必须要有某个对象。
public String login3(@SessionAttribute People people) {
System.out.println(people.getName());
return "redirect:/jsp/login.jsp";
}
关于post请求中文乱码问题
添加过滤器,springmvc提供过滤器。
encoding
UTF-8
forceEncoding
true
characterEncodingFilter
/*
关于form表单提交数据方式
方式一:通过属性名绑定
put people
@PutMapping("/put")
@ResponseBody//需要额外的json包的支持
public String putPeople(String name,String sex){
System.out.println(name+":"+sex);
// Map 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 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
@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
后台传json给前端
1.导入json解析依赖
com.fasterxml.jackson.core
jackson-databind
2.9.8
com.fasterxml.jackson.core
jackson-core
2.9.8
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:
前台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依赖
com.fasterxml.jackson.dataformat
jackson-dataformat-xml
2.9.8
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.加入依赖
commons-fileupload
commons-fileupload
1.4
2.在springmvc配置文件中注册文件上传解析器
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" %>
Title
单文件提交:
多文件提交:
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 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.配置拦截器
控制类:
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配置中配置的顺序有关。配置在前的先执行。
前置处理与后置处理顺序刚好相反。