无法使用spring框架在请求映射中获取不同的内容类型?

时间:2015-09-04 16:57:00

标签: spring spring-mvc spring-restcontroller spring-rest

这是我的控制器类:

@Controller
@RequestMapping("/actuator")
public class HealthController {

    @RequestMapping(value = "/metrics", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON)
    @ResponseBody
    public HealthModel getDump() throws JsonProcessingException {
        return new HealthModel();
        //return mapper.writeValueAsString(metrics.invoke());
    }

    @RequestMapping(value = "/metrics", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN)
    @ResponseBody
    public String getHealth() {
        return "HEALTHY";
    }
}

模型

public class HealthModel {

    @JsonProperty
    private String status;
    @JsonProperty
    private int id;

    public HealthModel(){
        this.status="WARN";
        this.id=2;
    }

}

注意我已将/metrics映射为返回jsonplain-text,具体取决于请求中的Accept Header

当我在

提出请求时

curl -v -H "Accept: application/json" http://localhost:8080/myapp/actuator/metrics

我在json得到了预期的回应 {"status":"WARN","id":2}

然而,当我尝试

curl -v -H "Accept: text/plain" http://localhost:8080/myapp/actuator/metrics

我得到HTTP/1.1 406 Not Acceptable

修改

@EnableWebMvc
@Configuration
public class AppMvcConfig extends WebMvcConfigurerAdapter {

   @Resource(name = "appObjectMapper")
    private ObjectMapper appObjectMapper;

    @Resource(name = "modelObjectMapper")
    private ObjectMapper modelObjectMapper;

 @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

        final MappingJackson2HttpMessageConverter inputConverter = new MappingJackson2HttpMessageConverter();
        inputConverter.setObjectMapper(appObjectMapper);

        final MappingJackson2HttpMessageConverter outputConverter = new MappingJackson2HttpMessageConverter();
        outputConverter.setObjectMapper(modelObjectMapper);

        converters.add(new JacksonDualMapperConverter(appObjectMapper, modelObjectMapper));

        super.configureMessageConverters(converters);
    }

}

3 个答案:

答案 0 :(得分:3)

由于您要添加自定义MessageConverter configureMessageConverters,因此会关闭默认转换器注册(see JavaDoc)。

因此,当内容协商开始时,您只有一个消息转换器(Jackson one)只支持JSON媒体类型,并且不知道如何处理text/plain

您应该在列表中添加StringHttpMessageConverter以支持text/plain

converters.add(new StringHttpMessageConverter());

答案 1 :(得分:2)

根据文档,using Cryptware.NCryptoki; using iTextSharp.text; using iTextSharp.text.log; using iTextSharp.text.pdf; using iTextSharp.text.pdf.security; using Org.BouncyCastle.Security; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; namespace _07SignWithPKCS11DLL { class Program { static void Main(string[] args) { LoggerFactory.GetInstance().SetLogger(new SysoLogger()); // Creates a Cryptoki object related to the specific PKCS#11 native library Cryptoki cryptoki = new Cryptoki("cvP11.dll"); cryptoki.Initialize(); // Reads the set of slots containing a token SlotList slots = cryptoki.Slots; if (slots.Count == 0) { Console.WriteLine("No slot available"); Console.ReadLine(); return; } // Gets the first slot available Slot slot = slots[0]; if (!slot.IsTokenPresent) { Console.WriteLine("No token inserted in the slot: " + slots[0].Info.Description); Console.ReadLine(); return; } // Gets the first token available Token token = slot.Token; // Opens a read serial session Session session = token.OpenSession(Session.CKF_SERIAL_SESSION, null, null); // Executes the login passing the user PIN int nRes = session.Login(Session.CKU_USER, "secret"); if (nRes != 0) { Console.WriteLine("Wrong PIN"); return; } CSignWithPKCS11SC.Smartcardsign(session, "PhilippEggerQualifiedSignature", "SwissSign_nonRep "); /* CryptokiCollection template = new CryptokiCollection(); template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_CERTIFICATE)); template.Add(new ObjectAttribute(ObjectAttribute.CKA_CERTIFICATE_TYPE, Certificate.CKC_X_509)); CryptokiCollection objects = session.Objects.Find(template, 10); // If the private keys is found continue if (objects.Count > 0) { foreach (Object obj in objects) { Cryptware.NCryptoki.X509Certificate cert = (Cryptware.NCryptoki.X509Certificate)obj; Console.WriteLine(cert.Label + " - " + cert.ID); } } */ // Logouts and closes the session session.Logout(); session.Close(); cryptoki.Finalize(IntPtr.Zero); Console.ReadLine(); } } class CryptokiPrivateKeySignature : IExternalSignature { private readonly Cryptware.NCryptoki.Session session; RSAPrivateKey privateKey; public CryptokiPrivateKeySignature(Session session, String alias) { this.session = session; CryptokiCollection template = new CryptokiCollection(); template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PRIVATE_KEY)); template.Add(new ObjectAttribute(ObjectAttribute.CKA_KEY_TYPE, Key.CKK_RSA)); // "SwissSign_nonRep " // "SwissSign_digSig " template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, alias)); /* CryptokiCollection objects = session.Objects.Find(template, 10); if (objects.Count > 0) { foreach (Object obj in objects) { RSAPrivateKey cert = (RSAPrivateKey)obj; Console.WriteLine(cert.Label); } } */ privateKey = (RSAPrivateKey)session.Objects.Find(template); } public String GetHashAlgorithm() { return "SHA1"; } public String GetEncryptionAlgorithm() { return "RSA"; } public byte[] Sign(byte[] message) { session.SignInit(Mechanism.SHA1_RSA_PKCS, privateKey); return session.Sign(message); } } class CSignWithPKCS11SC { public const String SRC = @"C:\Temp\test_to_sign.pdf"; public const String DEST = @"C:\Temp\test_to_sign-pkcs11.pdf"; //public const String DLL = "c:/windows/system32/beidpkcs11.dll"; public const String DLL = "c:/windows/system32/cvP11.dll"; public void Sign(String src, String dest, ICollection<Org.BouncyCastle.X509.X509Certificate> chain, Session session, String alias, String digestAlgorithm, CryptoStandard subfilter, String reason, String location, ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize) { // Creating the reader and the stamper PdfReader reader = null; PdfStamper stamper = null; FileStream os = null; try { reader = new PdfReader(src); os = new FileStream(dest, FileMode.Create); stamper = PdfStamper.CreateSignature(reader, os, '\0'); // Creating the appearance PdfSignatureAppearance appearance = stamper.SignatureAppearance; appearance.Reason = reason; appearance.Location = location; appearance.SetVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig"); // Creating the signature IExternalSignature pks = new CryptokiPrivateKeySignature(session, alias); MakeSignature.SignDetached(appearance, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter); } finally { if (reader != null) reader.Close(); if (stamper != null) stamper.Close(); if (os != null) os.Close(); } } public static void Smartcardsign(Session session, String alias, String aliasPrivateKey) { // Searchs for an RSA certificate object // Sets the template with its attributes CryptokiCollection template = new CryptokiCollection(); template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_CERTIFICATE)); template.Add(new ObjectAttribute(ObjectAttribute.CKA_CERTIFICATE_TYPE, Certificate.CKC_X_509)); template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, alias)); Cryptware.NCryptoki.X509Certificate nCert = (Cryptware.NCryptoki.X509Certificate)session.Objects.Find(template); if (nCert != null) { X509Certificate2 cert = Utils.ConvertCertificate(nCert); ICollection<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate>(); X509Chain x509chain = new X509Chain(); x509chain.Build(cert); foreach (X509ChainElement x509ChainElement in x509chain.ChainElements) { chain.Add(DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate)); } IOcspClient ocspClient = new OcspClientBouncyCastle(); List<ICrlClient> crlList = new List<ICrlClient>(); crlList.Add(new CrlClientOnline(chain)); TSAClientBouncyCastle tsaClient = new TSAClientBouncyCastle("http://tsa.swisssign.net"); CSignWithPKCS11SC app = new CSignWithPKCS11SC(); Console.WriteLine("Logged in? " + session.IsLoggedIn); app.Sign(SRC, DEST, chain, session, aliasPrivateKey, DigestAlgorithms.SHA256, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0); } else { Console.WriteLine("Certificate not found: " + alias); } } } } 表示返回类型应直接写入HTTP响应主体(而不是放在模型中,或解释为视图名称)。所以注释应该在那里。在第二次看,你的产品注释似乎不正确。 它应该是@ResponseBody而不是produces = MediaType.TEXT_PLAIN_VALUE。 我尝试了以下内容,它对我有用:

produces = MediaType.TEXT_PLAIN

您可能还需要添加StringHttpMessageConverter

答案 2 :(得分:1)

万一有人仍然收到Type mismatch: cannot convert from MediaType to String[]错误:

解决方案是使用 MediaType.APPLICATION_JSON_VALUE

而不是MediaType.APPLICATION_JSON

此致