Spring Config
1.说明
Java配置方式就是使用Java类来替代Spring原先的xml文件
2.实现方式
主要依赖于@Confuration和@Bean注解实现
@Confuration:使用在类上,说明该类是一个配置类相当于一个xml文件
@Bean:使用在方法上,作用是返回对象将对象保存在IOC容器中相当于XML文件中的bean标签
3.Config
@Configuration
@PropertySource(value="classpath:db.properties")
public class SpringConfig {
@Bean
public UserService userService(){
return new UserServiceImpl();
}
@Value("${mysql.username}")
private String username;
@Value("${password}")
private String password;
@Bean
public String username() {
return username;
}
@Bean
public String password() {
return password;
}
}
4.入口类
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean(UserService.class);
System.out.println(userService);
String username = (String) context.getBean("mysql.username");
String password = (String) context.getBean("mysql.password");
System.out.println(username);
System.out.println(password);
Springboot介绍
首先声明,Spring Boot不是一门新技术,所以不用紧张。从本质上来说,Spring
Boot就是Spring,它做了那些没有它你也会去做的Spring
Bean配置。它使用“习惯优于配置”(项目中存在大量的配置,此外还内置了一个习惯性
的配置,让你无需手动进行配置)的理念让你的项目快速运行起来。使用Spring
Boot很容易创建一个独立运行(运行jar,内嵌Servlet容器)、准生产级别的基于Spring
框架的项目,使用Spring Boot你可以不用或者只需要很少的Spring配置。
http://tengj.top/2017/04/24/springboot0/
SpringBoot
2.1 SpringBoot的好处
1.快速构建项目
2.对主流开发框架的无配置集成
3.项目可独立运行,无需外部依赖Servlet容器,springboot中内嵌一个tomcat
4.提高开发效率,部署效率
5.与云计算的天然集成
例如:
其实就是简单、快速、方便!平时如果我们需要搭建一个spring web项目的时候需要怎么做呢?
1)配置web.xml,加载spring和spring mvc
2)配置数据库连接、配置spring事务
3)配置加载配置文件的读取,开启注解
4)配置日志文件
...
配置完成之后部署tomcat 调试
...
现在非常流行微服务,如果我这个项目仅仅只是需要发送一个邮件,如果我的项目仅仅是生产一个积分;我都需要这样折腾一遍!
但是如果使用spring boot呢?
很简单,我仅仅只需要非常少的几个配置就可以迅速方便的搭建起来一套web项目或者是构建一个微服务!
第一个SpringBoot :HelloWorld
- 网页介绍
http://start.spring.io/
- pom.xml解析(父级依赖)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
3.应用入口类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@SpringBootApplication
public class Chapter1Application {
@RequestMapping("/")
public String index(){
return "Hello Spring Boot";
}
public static void main(String[] args) {
SpringApplication.run(Chapter1Application.class, args);
}
}
4.解决报错问题
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.3.0.Final</version>
</dependency>
SpringBoot原理
Banner
如果我们想改动,那么只需要在src/main/recesources下新建一个banner.txt文件
实际上Spring Boot在这个位置,放了一个彩蛋,我们是可以自定义这个图标的。
我们可以在resource目录下面放入一个banner.txt文件,
Spring Boot启动项目的时候就会优先启动这个文件中的内容。
http://patorjk.com/software/taag/#p=display&f=Graffiti&t=Type%20Something%20
SpringBoot配置文件(application.properties)
http://tengj.top/2017/02/28/springbootconfig/
mybatis
#指定bean所在包
mybatis.type-aliases-package=com.dudu.domain
#指定映射文件
mybatis.mapperLocations=classpath:mapper/*.xml
spring.datasource.url=jdbc:mysql://localhost:3306/work1?useUnicode=true&characterEncoding=UTF8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
mybatis注解
# crud
# 名称不一致
@Select("select * from book where id = #{id}")
@Results({
@Result(property="id",column="id",id=true),
@Result(property="name",column="b_name"),
@Result(property="createTime",column="b_create_time"),
@Result(property="price",column="price")
})
public Book findById(int id);
# 一对一
@Select("select * from chapter")
@Results({
@Result(property = "id", column = "id",id=true),
@Result(property = "name", column = "name"),
@Result(property = "bookId", column = "book_id"),
@Result(property = "book",column="book_id",one = @One(fetchType=FetchType.EAGER,select="com.zhiyou100.mapper.BookMapper.findById"))
})
public List<Chapter> findAll();
# 一对多
@Select("select * from book")
//解决数据库和java属性不一致
//property:java属性
//column:数据库属性
//id:判断是否是主键
@Results({
@Result(property="id",column="id",id=true),
@Result(property="name",column="b_name"),
@Result(property="createTime",column="b_create_time"),
@Result(property="price",column="price"),
@Result(property="chapters",column="id",many=@Many(fetchType=FetchType.EAGER,select="com.zhiyou100.mapper.ChapterMapper.findByBookId"))
})
public List<Book> findAll();
# 多对多
@Select("select * from user")
@Results({
@Result(property="id",column="id",id=true),
@Result(property="roles",column="id",many=@Many(fetchType=FetchType.EAGER,select="com.zhiyou100.mapper.RoleMapper.findByUserId"))
})
public List<User> findUserAndRole();
@Select("SELECT * from role r INNER JOIN user_role ur ON r.id = ur.role_id where ur.user_id = #{userId}")
public List<Role> findByUserId(int userId);
SpringBoot模版(templates:thymeleaf)
- Jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 配置文件
spring.thymeleaf.cache=true
spring.thymeleaf.check-template=true
spring.thymeleaf.check-template-location=true
spring.thymeleaf.content-type=text/html
spring.thymeleaf.enabled=true
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.excluded-view-names=
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
- 头文件导入
<html xmlns:th="http://www.thymeleaf.org">
4.文本显示
<td th:text="${learn.author}"></td>
5.链接显示
<a th:text="${page}" th:href="@{/order/details(orderId=${page})}">
</a>
6.for循环表达(3种)
遍历数组
<tr th:each="learn : ${learnList}">
<td th:text="${learn.author}"></td>
<td th:text="${learn.title}"></td>
<td th:text="${learn.url}"></td>
</tr>
遍历数组:详细版本
<tr th:each="learn,item : ${learnList}">
<td th:text="${item}"></td>
<td th:text="${learn.author}"></td>
<td th:text="${learn.title}"></td>
<td th:text="${learn.url}"></td>
</tr>
循环指定次数
<span th:each="page :${#numbers.sequence(1,count)}">
</span>
6.条件表达式
<tr th:class="${row.even}? 'even' : 'odd'">
</tr>
7 switch
<p th:switch="${page}">
<font th:case="1"> 匹配1 </font>
<font th:case="2"> 匹配2</font>
<font th:case="*">默认匹配</font>
</p>
8.其他作用域访问
${param.x} 返回名为x 的 request参数。(可能有多个值)
${session.x} 返回名为x的Session参数。
${application.x} 返回名为 servlet application context 的参数。
9.if
th:if="${xx} lt 'x'"
gt:great than(大于)>
ge:great equal(大于等于)>=
eq:equal(等于)==
lt:less than(小于)<
le:less equal(小于等于)<=
ne:not equal(不等于)!=
SpringBoot静态文件(static:js、css)
log日志
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
代码输出
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 此xml在spring-boot-1.5.3.RELEASE.jar里 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<!-- 开启后可以通过jmx动态控制日志级别(springboot Admin的功能) -->
<!--<jmxConfigurator/>-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--<File>/home/hfw-client/hfw_log/stdout.log</File>-->
<File>D:/log/hfw-client/hfw_log/stdout.log</File>
<encoder>
<pattern>%date [%level] [%thread] %logger{60} [%file : %line] %msg%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 添加.gz 历史日志会启用压缩 大大缩小日志文件所占空间 -->
<!--<fileNamePattern>/home/hfw-client/hfw_log/stdout.log.%d{yyyy-MM-dd}.log</fileNamePattern>-->
<fileNamePattern>D:/log/hfw-client/hfw_log/stdout.log.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory><!-- 保留30天日志 -->
</rollingPolicy>
</appender>
<logger name="com.zhiyou100" level="DEBUG" />
<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
Maven下载失败
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.List;
/**
* 删除maven下载失败的目录
* <pre>
* 先搜索 存在 lastUpdated的文件(即jar文件等),
* 然后再删除此文件的目录
* </pre>
*/
public class DeleteMavenDownloadfailedFile {
/**声明统计文件个数的变量*/
static int countFiles = 0;
/**声明统计文件夹的变量*/
static int countFolders = 0;
/**
*递归查找包含关键字的文件
*/
public static File[] searchFile(File folder, final String keyWord) {
File[] subFolders = folder.listFiles(new FileFilter() {// 运用内部匿名类获得文件
public boolean accept(File pathname) {// 实现FileFilter类的accept方法
if (pathname.isFile()) {// 如果是文件
countFiles++;
} else {
// 如果是目录
countFolders++;
}
if (pathname.isDirectory()
|| (pathname.isFile() && pathname.getName().toLowerCase().contains(keyWord.toLowerCase()))) {// 目录或文件包含关键字
return true;
}
return false;
}
});
List<File> result = new ArrayList<File>();// 声明一个集合
for (int i = 0; i < subFolders.length; i++) {// 循环显示文件夹或文件
if (subFolders[i].isFile()) {// 如果是文件则将文件添加到结果列表中
result.add(subFolders[i]);
} else {// 如果是文件夹,则递归调用本方法,然后把所有的文件加到结果列表中
File[] foldResult = searchFile(subFolders[i], keyWord);
for (int j = 0; j < foldResult.length; j++) {// 循环显示文件
result.add(foldResult[j]);// 文件保存到集合中
}
}
}
File files[] = new File[result.size()];// 声明文件数组,长度为集合的长度
result.toArray(files);// 集合数组化
return files;
}
public static File[] find(String root, String keyword) {
File folder = new File(root);// 默认目录
if (!folder.exists()) {// 如果文件夹不存在
System.out.println("目录不存在:" + folder.getAbsolutePath());
return null;
}
File[] result = searchFile(folder, keyword);// 调用方法获得文件数组
return result;
}
/**
* 删除文件和目录
*
* 注意:根据业务场景,此方法没有采用递归删除
*
* @param file
*/
public static void delete(File file) {
if (file.exists()) {
if (file.isFile()) {
boolean bb = file.delete();
System.out.println(file.getAbsolutePath() + " 删除状态:" + bb);
} else if (file.isDirectory()) {
File files[] = file.listFiles();
for (int i = 0; i < files.length; i++) {
File _file = files[i];
boolean bb = _file.delete();
System.out.println(" " + _file.getAbsolutePath() + " 删除状态:" + bb);
}
}
boolean bb = file.delete();
System.out.println(file.getAbsolutePath() + " 删除状态:" + bb);
} else {
System.out.println("所删除的文件不存在!" + file.getAbsolutePath());
}
}
public static void main(String[] args) {
String root = "E:\\lee\\maven";
String keyword = "lastUpdated";
File[] result = find(root, keyword);
if (result == null ) {
return;
}
if (result.length == 0) {
System.out.println("查找文件为 0");
return;
}
System.out.println("在 " + root + " 以及所有子文件时查找对象" + keyword);
System.out.println("查找了" + countFiles + " 个文件," + countFolders + " 个文件夹,共找到 " + result.length + " 个符合条件的文件:");
for (int i = 0; i < result.length; i++) {// 循环显示文件
File file = result[i];
delete(new File(file.getParentFile().getAbsolutePath()));
// System.out.println(file.getAbsolutePath() +
// " == "+file.getParentFile().getAbsolutePath());// 显示文件绝对路径
}
}
}
Shiro和SpringBoot结合
package com.zhiyou100.config;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.zhiyou100.realm.UserRealm;
import java.util.HashMap;
import java.util.Map;
import org.apache.shiro.mgt.SecurityManager;
@Configuration
public class ShiroConfig {
@Autowired
UserRealm userRealm;
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(userRealm);
return manager;
}
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(securityManager);
bean.setLoginUrl("/login.html");
bean.setUnauthorizedUrl("/error.html");
Map<String, String> map = new HashMap<String, String>();
map.put("/css/**", "anon");
map.put("/img/**", "anon");
map.put("/user/login.do", "anon");
map.put("/login.html", "anon");
map.put("/error.html", "anon");
map.put("/**", "authc");
bean.setFilterChainDefinitionMap(map);
return bean;
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
return creator;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
return new AuthorizationAttributeSourceAdvisor();
}
}
thymeleaf和shiro结合
添加依赖
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
在shiro的configuration中配置
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
在html中加入xmlns
<html lang="zh_CN" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
使用
# 判断是否有角色
shiro:hasRole="user"
# 判断是否有权限
shiro:hasPermission="update"
# 获取当前登录的账号,account代表调用account属性
shiro:principal property="account"
例如:
<span shiro:authenticated="true" >
<span>欢迎您:<span th:text="${userInfo.realName}"></span></span>
</span>
<div shiro:hasPermission="update">
<a href="/2">2222</a>
</div>