🔖 javaapp
parent
ef9e43e817
commit
52094ec137
|
@ -52,6 +52,23 @@
|
|||
<version>${tomcat.version}</version>
|
||||
</dependency>
|
||||
<!-- tomcat end -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.9.6</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package io.github.dunwu.app;
|
||||
package io.github.dunwu;
|
||||
|
||||
import java.io.File;
|
||||
import org.apache.catalina.Server;
|
|
@ -0,0 +1,103 @@
|
|||
package io.github.dunwu.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 跨域过滤器,根据正则进行匹配
|
||||
*/
|
||||
public class CorsFilter implements Filter {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CorsFilter.class);
|
||||
|
||||
private String regex;
|
||||
private String headerKey;
|
||||
private String protocol = "http";
|
||||
private final String ORIGIN_KEY = "Origin";
|
||||
|
||||
public void init(FilterConfig filterConfig) {
|
||||
// 取配置参数
|
||||
regex = filterConfig.getInitParameter("regex");
|
||||
headerKey = filterConfig.getInitParameter("headerKey");
|
||||
String protocolVal = filterConfig.getInitParameter("protocol");
|
||||
if (StringUtils.isNotBlank(protocolVal)) {
|
||||
if (StringUtils.equalsIgnoreCase("http", protocolVal)
|
||||
|| StringUtils.equalsIgnoreCase("https", protocolVal)) {
|
||||
protocol = protocolVal.toLowerCase();
|
||||
} else {
|
||||
logger.error("CorsFilter 配置参数 protocol 非法,仍使用默认值 http");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
|
||||
if (StringUtils.isBlank(regex) || StringUtils.isBlank(headerKey)) {
|
||||
throw new ServletException("读取跨域过滤器的配置参数失败");
|
||||
}
|
||||
|
||||
// 读取请求地址的域
|
||||
String domain = httpRequest.getHeader(headerKey);
|
||||
String origin = httpRequest.getHeader(ORIGIN_KEY);
|
||||
|
||||
if (StringUtils.isBlank(origin)) {
|
||||
logger.debug("origin 为空, 跳过检查");
|
||||
chain.doFilter(httpRequest, httpResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(domain)) {
|
||||
logger.debug("domain 为空, 跳过检查");
|
||||
chain.doFilter(httpRequest, httpResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
if (origin.toLowerCase().contains(domain.toLowerCase())) {
|
||||
// 判断请求方和应答方是否同为 http 或 https
|
||||
// 如果相同,这里视为同源;否则,视为跨域
|
||||
if (origin.startsWith(protocol)) {
|
||||
logger.debug("domain={}, origin={}, 二者协议相同,且域名同源,跳过检查", domain, origin);
|
||||
chain.doFilter(httpRequest, httpResponse);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
if (!pattern.matcher(origin).matches()) {
|
||||
logger.warn("客户端域 origin={} 不在跨域白名单中", origin);
|
||||
httpResponse.sendError(403, "客户端域不在跨域白名单中");
|
||||
throw new ServletException("客户端域不在跨域白名单中");
|
||||
}
|
||||
|
||||
logger.debug("对 origin={} 放开跨域限制", origin);
|
||||
httpResponse.addHeader("Access-Control-Allow-Origin", origin);
|
||||
httpResponse.addHeader("Access-Control-Allow-Credentials", "true");
|
||||
httpResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS, DELETE");
|
||||
httpResponse.addHeader("Access-Control-Allow-Headers",
|
||||
"DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since," +
|
||||
" Cache-Control, Content-Type, Content-Range, Range, X-CSRF-TOKEN");
|
||||
httpResponse.addHeader("Access-Control-Expose-Headers",
|
||||
"DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since," +
|
||||
" Cache-Control, Content-Type, Content-Range, Range");
|
||||
if (httpRequest.getMethod().equals("OPTIONS")) {
|
||||
httpResponse.setStatus(HttpServletResponse.SC_OK);
|
||||
return;
|
||||
}
|
||||
chain.doFilter(httpRequest, httpResponse);
|
||||
}
|
||||
|
||||
public void destroy() {}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package io.github.dunwu.util;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public class IOObjectMapper extends ObjectMapper {
|
||||
public IOObjectMapper() {
|
||||
this.setSerializationInclusion(Include.NON_EMPTY);
|
||||
this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package io.github.dunwu.web.controller;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.github.dunwu.web.dto.BaseResponseDTO;
|
||||
import io.github.dunwu.web.dto.MenuDTO;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* 配合前端请求的 API 接口
|
||||
* @author zhangpeng0913
|
||||
* @date 2017/8/23.
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "/api")
|
||||
public class ApiController {
|
||||
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/menu", method = RequestMethod.GET)
|
||||
public BaseResponseDTO getAll(HttpServletRequest request) throws JsonProcessingException {
|
||||
String data = request.getParameter("data");
|
||||
BaseResponseDTO baseResponseDTO = new BaseResponseDTO();
|
||||
baseResponseDTO.setData(getAll());
|
||||
ObjectMapper om = new ObjectMapper();
|
||||
System.out.println("ResponseDTO: " + om.writeValueAsString(baseResponseDTO));
|
||||
return baseResponseDTO;
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/login")
|
||||
public BaseResponseDTO login(@RequestBody Map<String, String> map) throws IOException {
|
||||
String username = map.get("username");
|
||||
String password = map.get("password");
|
||||
BaseResponseDTO<Map<String, String>> baseResponseDTO = new BaseResponseDTO();
|
||||
if (StringUtils.equals(username, "admin") && StringUtils.equals(password, "123456")) {
|
||||
Map<String, String> result = new HashMap<String, String>();
|
||||
result.put("name", "admin");
|
||||
result.put("role", "ADMIN");
|
||||
result.put("uid", "1");
|
||||
baseResponseDTO.setData(result);
|
||||
System.out.println(baseResponseDTO.toString());
|
||||
return baseResponseDTO;
|
||||
} else {
|
||||
baseResponseDTO.setCode(BaseResponseDTO.DEFAULT_RESPONSE_RESULT.SYSTEM_ERROR.value());
|
||||
baseResponseDTO.getMessages().add(BaseResponseDTO.DEFAULT_RESPONSE_RESULT.SYSTEM_ERROR.desc());
|
||||
return baseResponseDTO;
|
||||
}
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/logout", method = RequestMethod.GET)
|
||||
public BaseResponseDTO logout(HttpServletRequest request) {
|
||||
BaseResponseDTO baseResponseDTO = new BaseResponseDTO();
|
||||
return baseResponseDTO;
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/my", method = RequestMethod.GET)
|
||||
public BaseResponseDTO my(HttpServletRequest request) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("name", "admin");
|
||||
map.put("role", "ADMIN");
|
||||
map.put("uid", "1");
|
||||
BaseResponseDTO baseResponseDTO = new BaseResponseDTO();
|
||||
baseResponseDTO.setData(map);
|
||||
return baseResponseDTO;
|
||||
}
|
||||
|
||||
private static Set<MenuDTO> getAll() {
|
||||
MenuDTO item0 = new MenuDTO("0", "首页", "home", "Item", "/pages/home");
|
||||
|
||||
MenuDTO subMenu1 = new MenuDTO("1", "业务", "bars", "SubMenu", null);
|
||||
MenuDTO item11 = new MenuDTO("11", "Mailbox", "mail", "Item", "/pages/mailbox");
|
||||
MenuDTO item12 = new MenuDTO("12", "用户列表", "user", "Item", "/pages/user");
|
||||
subMenu1.addChild(item11);
|
||||
subMenu1.addChild(item12);
|
||||
|
||||
MenuDTO subMenu2 = new MenuDTO("2", "Others", "coffee", "SubMenu", null);
|
||||
MenuDTO itemGroup1 = new MenuDTO("21", "Group1", "windows-o", "ItemGroup", null);
|
||||
MenuDTO item22 = new MenuDTO("22", "Group1-1", null, "Item", null);
|
||||
MenuDTO divider = new MenuDTO("23", "Divider1", null, "Divider", null);
|
||||
MenuDTO itemGroup2 = new MenuDTO("24", "Group2", "apple-o", "ItemGroup", null);
|
||||
MenuDTO item25 = new MenuDTO("25", "Group2-1", null, "Item", null);
|
||||
itemGroup1.addChild(item22);
|
||||
itemGroup2.addChild(item25);
|
||||
subMenu2.addChild(itemGroup1);
|
||||
subMenu2.addChild(divider);
|
||||
subMenu2.addChild(itemGroup2);
|
||||
|
||||
Set<MenuDTO> menus = new TreeSet<MenuDTO>();
|
||||
menus.add(item0);
|
||||
menus.add(subMenu1);
|
||||
menus.add(subMenu2);
|
||||
|
||||
return menus;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package io.github.dunwu.app.controller;
|
||||
package io.github.dunwu.web.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* The Apache License 2.0 Copyright (c) 2016 Zhang Peng
|
||||
*/
|
||||
package io.github.dunwu.app.controller;
|
||||
package io.github.dunwu.web.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
@ -0,0 +1,87 @@
|
|||
package io.github.dunwu.web.dto;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class BaseResponseDTO<T> {
|
||||
|
||||
private Integer code = DEFAULT_RESPONSE_RESULT.SUCCESS.value();
|
||||
|
||||
private final List<String> messages = new ArrayList<>();
|
||||
|
||||
private T data;
|
||||
|
||||
public BaseResponseDTO() {}
|
||||
|
||||
public BaseResponseDTO(T dto) {
|
||||
this.data = dto;
|
||||
}
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(Integer code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public void addError(String error) {
|
||||
this.messages.add(error);
|
||||
}
|
||||
|
||||
public void addErrors(String[] errors) {
|
||||
this.addErrors(Arrays.asList(errors));
|
||||
}
|
||||
|
||||
public void addErrors(List<String> errorList) {
|
||||
this.messages.addAll(errorList);
|
||||
}
|
||||
|
||||
public void removeError(String error) {
|
||||
this.messages.remove(error);
|
||||
}
|
||||
|
||||
public List<String> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public enum DEFAULT_RESPONSE_RESULT {
|
||||
SUCCESS(0, "[]"), // 成功
|
||||
AUTHEN_FAIL(-1, "认证失败"), // 认证失败
|
||||
AUTHOR_FAIL(-2, "权限不足"), // 授权不足
|
||||
PARAM_CHECK_FAIL(-3, ""), // 参数校验失败,错误信息交由业务逻辑处理
|
||||
RESOURCE_NOT_EXIST(-4, "请求资源不存在"), // 请求资源不存在
|
||||
SYSTEM_ERROR(-5, "系统错误"),
|
||||
DATA_MALFORMAT(-6, "请求参数数据格式不正确"),
|
||||
REQMETHOD_ERROR(-7, "请求方法不正确"),
|
||||
TYPE_MISMATCH(-8, "请求参数类型不匹配"),
|
||||
MISS_REQUEST_PARAM(-9, "请求参数缺失");
|
||||
|
||||
private final Integer value;
|
||||
|
||||
private final String desc;
|
||||
|
||||
DEFAULT_RESPONSE_RESULT(int value, String desc) {
|
||||
this.value = value;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String desc() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package io.github.dunwu.web.dto;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
public class MenuDTO implements Cloneable, Comparable<MenuDTO> {
|
||||
|
||||
private String key;
|
||||
|
||||
private String title;
|
||||
|
||||
private String icon;
|
||||
|
||||
private String type;
|
||||
|
||||
private String url;
|
||||
|
||||
private final Set<MenuDTO> children = new TreeSet<MenuDTO>();
|
||||
|
||||
public MenuDTO() {}
|
||||
|
||||
public MenuDTO(String key, String title, String icon, String type, String url) {
|
||||
this.key = key;
|
||||
this.title = title;
|
||||
this.icon = icon;
|
||||
this.type = type;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public MenuDTO clone() throws CloneNotSupportedException {
|
||||
super.clone();
|
||||
MenuDTO menuDTO = new MenuDTO();
|
||||
menuDTO.setType(type);
|
||||
menuDTO.setKey(key);
|
||||
menuDTO.setTitle(title);
|
||||
menuDTO.setIcon(icon);
|
||||
menuDTO.setUrl(url);
|
||||
menuDTO.setUrl(url);
|
||||
return menuDTO;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void setIcon(String icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public Set<MenuDTO> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public void addChild(MenuDTO child) {
|
||||
this.children.add(child);
|
||||
}
|
||||
|
||||
public void addChildren(Set<MenuDTO> children) {
|
||||
this.children.addAll(children);
|
||||
}
|
||||
|
||||
public void addChildren(MenuDTO[] children) {
|
||||
this.children.addAll(Arrays.asList(children));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
boolean equals = false;
|
||||
if (obj instanceof MenuDTO) {
|
||||
MenuDTO menuDTO = (MenuDTO) obj;
|
||||
equals = (new EqualsBuilder().append(url, menuDTO.getUrl())).isEquals();
|
||||
}
|
||||
return equals;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37).append(url).toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(MenuDTO otherMenuDTO) {
|
||||
return new CompareToBuilder().append(key, otherMenuDTO.getKey()).append(url, otherMenuDTO.getUrl())
|
||||
.toComparison();
|
||||
}
|
||||
}
|
|
@ -12,11 +12,19 @@
|
|||
|
||||
<!-- 启动注解服务 -->
|
||||
<mvc:annotation-driven/>
|
||||
<context:component-scan base-package="io.github.dunwu.app"/>
|
||||
<context:component-scan base-package="io.github.dunwu.web"/>
|
||||
|
||||
<!-- 视图解析器 -->
|
||||
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
|
||||
<property name="prefix" value="/views/jsp/"/>
|
||||
<property name="suffix" value=".jsp"/>
|
||||
</bean>
|
||||
|
||||
<bean id="jacksonObjectMapper" name="jacksonObjectMapper"
|
||||
class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
|
||||
<property name="indentOutput" value="true" />
|
||||
<property name="objectMapper">
|
||||
<bean class="io.github.dunwu.util.IOObjectMapper" />
|
||||
</property>
|
||||
</bean>
|
||||
</beans>
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Manifest-Version: 1.0
|
||||
Main-Class: io.github.dunwu.app.Main
|
||||
Main-Class: io.github.dunwu.Main
|
||||
|
|
|
@ -39,6 +39,24 @@
|
|||
<dispatcher>REQUEST</dispatcher>
|
||||
<dispatcher>FORWARD</dispatcher>
|
||||
</filter-mapping>
|
||||
|
||||
<filter>
|
||||
<filter-name>CorsFilter</filter-name>
|
||||
<filter-class>io.github.dunwu.filter.CorsFilter</filter-class>
|
||||
<init-param>
|
||||
<param-name>headerKey</param-name>
|
||||
<param-value>Host</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>regex</param-name>
|
||||
<!--<param-value>((http://)|(https://))?(\w*\.)*(demo*.com|demo*)(\S)*</param-value>-->
|
||||
<param-value>((http://)|(https://))?(\w*\.)*(\S)*</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>CorsFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
<!-- FILTER END -->
|
||||
|
||||
<welcome-file-list>
|
||||
|
|
Loading…
Reference in New Issue